如果颜色最多个数大于其它颜色之和,可以匹配的对数就是其它颜色之和,即其它颜色的都和颜色最多的两两匹配
反之,每个颜色都能找到匹配,因为其它颜色匹配后,剩下的只要不断拿出两个去拆已经匹配了的一对,一定能用完。
MyCode:
#include<bits/stdc++.h> using namespace std; const int maxn=2e5+7,maxm=4e5+7; typedef long long ll; inline ll read(){ ll s = 0, w = 1; char ch = getchar(); while (ch < 48 || ch > 57) { if (ch == '-') w = -1; ch = getchar(); } while (ch >= 48 && ch <= 57) s = (s << 1) + (s << 3) + (ch ^ 48), ch = getchar(); return s * w; } int head[maxn],Next[maxm],to[maxm],tot; void add(int x,int y) { to[++tot]=y; Next[tot]=head[x]; head[x]=tot; } int size[maxn],son[maxn]; int ans[maxn],cnt[maxn],col[maxn],sum[maxn],num,maxx; bool vis[maxn]; bool cmp(int &a,int &b) { return cnt[a]>cnt[b]; } void dfs(int x,int f) { size[x]=1; for(int i=head[x],y=to[i];i;i=Next[i],y=to[i]) { if(y==f) continue; dfs(y,x); size[x]+=size[y]; if(size[son[x]]<size[y]) son[x]=y; } } void calc(int x,int f) { cnt[col[x]]+=sum[x]; num+=sum[x]; if(cnt[col[x]]>maxx) maxx=cnt[col[x]]; for(int i=head[x],y=to[i];i;i=Next[i],y=to[i]) { if(y==f||vis[y]) continue; calc(y,x); } } void delet(int x,int f) { cnt[col[x]]-=sum[x]; for(int i=head[x];i;i=Next[i]) if(to[i]!=f) delet(to[i],x); } void dsu(int x,int f,bool opt) { for(int i=head[x],y=to[i];i;i=Next[i],y=to[i]) { if(y==f||son[x]==y) continue; dsu(y,x,false); } if(son[x]) { dsu(son[x],x,true); vis[son[x]]=true; } calc(x,f); if(num-maxx*2>=0) ans[x]=num/2; else ans[x]=num-maxx; if(son[x]) vis[son[x]]=false; if(!opt) { delet(x,f); num=maxx=0; } } int main() { int n=read(); for(int i=2,u,v;i<=n;++i) { u=read(),v=read(); add(u,v); add(v,u); } for(int i=1;i<=n;++i) col[i]=read(),sum[i]=read(); dfs(1,0); dsu(1,0,false); for(int i=1;i<=n;++i) printf("%d\n",ans[i]); return 0; }