codeforces 690F2 Tree of Life (medium) 树hash
2016-09-05 18:57
375 查看
题意:一棵树,分别给出去掉第i个点之后剩下的图,点的顺序打乱,图的顺序打乱,求这棵树原来长什么样。n<=100
一定有一个图是去掉一个叶子节点之后的,找到这个图,枚举叶子加到哪,然后对于加完叶子的树枚举删掉一个点,把删完点的图hash出来扔到multiset里,再看其他图hash出来的值和这个multiset里的东西一不一样就行了。
无根树hash需要先找到重心,从重心hash,如果有两个重心还要在之间多加一个点。hash时将叶子的hash值排个序,hash出来就行了。
哦,顺便一提,我的是最短代码。
upd 广告:觉得这道题太水了么? 觉得树hash仅此而已了么 ?
请看下篇题解codeforces 690F3 Tree of Life (hard)。
spoiler alert : 对于下一道题可能引起的不适反应,请自备纸带。
一定有一个图是去掉一个叶子节点之后的,找到这个图,枚举叶子加到哪,然后对于加完叶子的树枚举删掉一个点,把删完点的图hash出来扔到multiset里,再看其他图hash出来的值和这个multiset里的东西一不一样就行了。
无根树hash需要先找到重心,从重心hash,如果有两个重心还要在之间多加一个点。hash时将叶子的hash值排个序,hash出来就行了。
哦,顺便一提,我的是最短代码。
upd 广告:觉得这道题太水了么? 觉得树hash仅此而已了么 ?
请看下篇题解codeforces 690F3 Tree of Life (hard)。
spoiler alert : 对于下一道题可能引起的不适反应,请自备纸带。
#include <bits/stdc++.h> using namespace std; #define N 110 #define ull unsigned long long #define seed 11333333 int n,T; multiset<ull>se; multiset<ull>::iterator it; ull val ; struct tree { int m,top,f1,f2,sum,id; int vis ,size ,used ,f ; vector<int>v ; vector<ull>v1 ; ull st ; void dfs1(int x,int y) { size[x]=1;used[x]=1; for(int i=0,t;i<v[x].size();i++) if((t=v[x][i])!=y&&!vis[t]) dfs1(t,x),size[x]+=size[t]; } void dfs2(int x,int y) { f[x]=sum-size[x]; for(int i=0,t;i<v[x].size();i++) if((t=v[x][i])!=y&&!vis[t]) dfs2(t,x),f[x]=max(f[x],size[t]); if(f[x]<f[f1])f1=x; else if(f[x]<f[f2])f2=x; } ull dfs3(int x,int y) { v1[x].clear(); for(int i=0,t;i<v[x].size();i++) if((t=v[x][i])!=y&&!vis[t]) v1[x].push_back(dfs3(t,x)); sort(v1[x].begin(),v1[x].end()); ull ret=1; for(int i=0;i<v1[x].size();i++) ret=ret*seed+v1[x][i]; return ret; } ull cal(int x) { f1=f2=0;f[0]=1<<30; dfs1(x,0); sum=size[x];dfs2(x,0); if(f[f1]!=f[f2]) return dfs3(f1,0); ull t1=dfs3(f1,f2); ull t2=dfs3(f2,f1); if(t1>t2)swap(t1,t2); return t1*seed+t2; } void init(int x) { scanf("%d",&m);id=x; for(int i=1;i<=n;i++)v[i].clear(); for(int i=1,x,y;i<=m;i++) { scanf("%d%d",&x,&y); v[x].push_back(y); v[y].push_back(x); } memset(used,0,sizeof(used)); top=0; for(int i=1;i<=n;i++) if(!used[i]) st[++top]=cal(i); sort(st+1,st+1+top);val[id]=0; for(int i=2;i<=top;i++) val[id]=val[id]*seed+st[i]; } int check() { se.clear(); for(int i=1;i<=n;i++) { vis[i]=1;top=0; for(int j=0;j<v[i].size();j++) st[++top]=cal(v[i][j]); vis[i]=0;ull tmp=0; sort(st+1,st+1+top); for(int j=1;j<=top;j++) tmp=tmp*seed+st[j]; se.insert(tmp); } for(int i=1;i<=n;i++) if(i!=id) { if((it=se.find(val[i]))==se.end()) return 0; se.erase(it); } return 1; } void print() { puts("YES"); for(int i=1;i<=n;i++) { for(int j=0,t;j<v[i].size();j++) if((t=v[i][j])<i) printf("%d %d\n",t,i); } } }tr ; void solve() { scanf("%d%*d",&n); for(int i=1;i<=n;i++) tr[i].init(i); for(int i=1;i<=n;i++) if(tr[i].top==2) { for(int j=1;j<=n;j++) if(tr[i].v[j].empty()) { for(int k=1;k<=n;k++) if(k!=j) { tr[i].v[k].push_back(j); tr[i].v[j].push_back(k); if(tr[i].check()) { tr[i].print(); return; } tr[i].v[k].pop_back(); tr[i].v[j].pop_back(); } } break; } puts("NO"); } int main() { //freopen("tt.in","r",stdin); scanf("%d",&T); while(T--) { solve(); } return 0; }
相关文章推荐
- codeforces 690 F3 Tree of Life (hard) 树hash
- Codeforces 690F1 - Tree of Life (easy)
- Tree of Life(easy) Codeforces 690F1
- Codeforces 690F1 - Tree of Life (easy)
- [Leetcode 236, Medium] Lowest Common Ancestor of a Binary Tree
- Leetcode 236. Lowest Common Ancestor of a Binary Tree (Medium) (cpp)
- Imbalance Value of a Tree (CodeForces 915F)
- [树的直径] Codeforces 804D Round #411 (Div. 1) D. Expected diameter of a tree
- 【CodeForces】915 F. Imbalance Value of a Tree 并查集
- 【LeetCode】289.Game of Life(Medium)解题报告
- Leetcode 289. Game of Life (Medium) (cpp)
- Medium 366题 Find Leaves of Binary Tree
- Medium 236题 Lowest Common Ancestor of a Binary Tree
- (medium)LeetCode 236.Lowest Common Ancestor of a Binary Tree
- 【CodeForces】576 B. Invariance of Tree
- 【LeetCode】236.Lowest Common Ancestor of a Binary Tree(Medium)解题报告
- Minimum Depth of Binary Tree Java
- Minimum Depth of Binary Tree
- Lowest Common Ancestor of a Binary Tree
- My Solution to Lowest Common Ancestor of a Binary Tree Part II (Node has parent Pointer)