虎(思維題+樹結構)
阿新 • • 發佈:2020-10-12
-
貪心
-
對於一個節點來說,顯然是對著的可以一條線連下來。所以偶數個的就正好是\(\frac{son}{2}\).
然後對於奇數個的,那就是讓偶數個先配上,剩下的一個向上傳,這個是不影響父節點的。
最後就是連邊的時候,對於已經染成黑色的就不必再建邊了。因為動一個已經黑色的不會更優。
對於最後顏色沒有要求的,這條邊就沒什麼用處,但是需要它來連線其他邊以達到更優解,所以用一種並查集的思想把這條邊縮起來,讓它的兒子和它的父親相連即可。
if(!y&&z)f[i]=to[x];
if(!z)to[i]=to[x];
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn=1e6+1; int n; int f[maxn],to[maxn]; bool vis[maxn]; int ANS=0; int head[maxn],len=0; struct E{int to,next,w;}e[maxn<<1]; void A(int x,int y){e[++len].to=y;e[len].next=head[x];head[x]=len;} int Find(int x){return f[x]==x?x:f[x]=Find(f[x]);} void Dfs(int u){ vis[u]=1; int cnt=0; for(int i=head[u];i;i=e[i].next){ int v=e[i].to; cnt++; //printf("%d %d %d\n",u,v,cnt); Dfs(v); }//printf("OvO %d %d\n",u,cnt); if(cnt&1){ if(f[u])ANS+=(cnt-1)/2; else ANS+=(cnt+1)/2; } else { ANS+=cnt/2; } } int main(){ freopen("tiger.in","r",stdin); freopen("tiger.out","w",stdout); scanf("%d",&n); for(int i=1;i<=n;i++)to[i]=i; for(int i=2;i<=n;i++){ int x,y,z;scanf("%d%d%d",&x,&y,&z); if(!y&&z)f[i]=to[x]; if(!z)to[i]=to[x]; }//for(int i=1;i<=n;i++)printf("%d fa=%d\n",i,f[i]); for(int i=1;i<=n;i++){ if(f[i])A(f[i],i); }for(int i=1;i<=n;i++){ if(!vis[i]){ Dfs(i); } }printf("%d\n",ANS); return 0; }