http://codeforces.com/contest/600/problem/E
暴力启发式合并就行了
提示:set的swap的复杂度是常数,这方面可以放心
我先打了一个很naive的算法
1 #include<cstdio> 2 #include<algorithm> 3 #include<vector> 4 #include<set> 5 #include<map> 6 using namespace std; 7 typedef long long LL; 8 typedef pair<LL,LL> P; 9 typedef set<P> s; 10 //P(颜色出现次数,颜色编号) 11 typedef map<LL,LL> m; 12 //颜色编号->颜色出现次数 13 typedef pair<s,m> P2; 14 LL n,anss[100100],c[100100]; 15 vector<LL> e[100100]; 16 P2 dfs(LL u,LL fa) 17 { 18 P2 t,ans; 19 ans.first.emplace(1,c[u]); 20 ans.second[c[u]]=1; 21 for(auto v:e[u]) 22 if(v!=fa) 23 { 24 t=dfs(v,u); 25 if(t.second.size()>ans.second.size()) swap(t,ans); 26 for(auto it:t.second) 27 { 28 ans.first.erase(P(ans.second[it.first],it.first)); 29 ans.second[it.first]+=it.second; 30 ans.first.emplace(ans.second[it.first],it.first); 31 } 32 } 33 int maxsz=ans.first.rbegin()->first; 34 for(auto it=ans.first.rbegin();it!=ans.first.rend()&&it->first==maxsz;it++) anss[u]+=it->second; 35 return ans; 36 } 37 int main() 38 { 39 LL i,x,y; 40 scanf("%lld",&n); 41 for(i=1;i<=n;i++) scanf("%lld",&c[i]); 42 for(i=1;i<n;i++) 43 { 44 scanf("%lld%lld",&x,&y); 45 e[x].push_back(y);e[y].push_back(x); 46 } 47 dfs(1,0); 48 for(i=1;i<=n;i++) printf("%lld ",anss[i]); 49 return 0; 50 }
毫不意外的被卡掉了~看第34行,怎么看都不对嘛
有两种解决方法:
第一种:每一个节点dfs的时候额外返回一个值,记录当前子树的答案。
第二种:将set换成另一个map<int,int>,记录颜色出现次数->编号之和
1 #include<cstdio> 2 #include<algorithm> 3 #include<vector> 4 #include<map> 5 using namespace std; 6 typedef long long LL; 7 typedef map<LL,LL> m; 8 //颜色出现次数->编号之和 9 //颜色编号->颜色出现次数 10 typedef pair<m,m> P2; 11 LL n,anss[100100],c[100100]; 12 vector<LL> e[100100]; 13 P2 dfs(LL u,LL fa) 14 { 15 P2 t,ans; 16 ans.first[1]=c[u]; 17 ans.second[c[u]]=1; 18 for(auto v:e[u]) 19 if(v!=fa) 20 { 21 t=dfs(v,u); 22 if(t.second.size()>ans.second.size()) swap(t,ans); 23 for(auto it:t.second) 24 { 25 ans.first[ans.second[it.first]]-=it.first; 26 ans.second[it.first]+=it.second; 27 ans.first[ans.second[it.first]]+=it.first; 28 } 29 } 30 anss[u]=ans.first.rbegin()->second; 31 return ans; 32 } 33 int main() 34 { 35 LL i,x,y; 36 scanf("%lld",&n); 37 for(i=1;i<=n;i++) scanf("%lld",&c[i]); 38 for(i=1;i<n;i++) 39 { 40 scanf("%lld%lld",&x,&y); 41 e[x].push_back(y);e[y].push_back(x); 42 } 43 dfs(1,0); 44 for(i=1;i<=n;i++) printf("%lld ",anss[i]); 45 return 0; 46 }
也可以将每个节点dfs返回的值改成全局变量(似乎可以避免一些玄学的常数问题)