BZOJ5203 [NEERC2017 Northern] Grand Test 【dfs树】【构造】
题目分析:
首先观察可知这是一个无向图,那么我们构建出它的dfs树。由于无向图的性质我们可以知道它的dfs树只有返祖边。考虑下面这样一个结论。
结论:若一个点的子树中(包含自己)有两个点有到它祖先的返祖边(不包括到它自己),
首先我们证明S和T肯定在DFS树中是祖先关系,接着证明到T至少有一条返祖边,那么这个结论就是显然的了。
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 const int maxn = 102000; 5 6 int n,m; 7 vector <int>g[maxn]; 8 9 int up[maxn],dep[maxn],wh[maxn],fa[maxn]; 10 int flag, from, to; 11 12 void read(){ 13 scanf("%d%d",&n,&m); 14 for(int i=1;i<=n;i++) g[i].clear(); 15 for(int i=1;i<=m;i++){ 16 int u,v; scanf("%d%d",&u,&v); 17 g[u].push_back(v); g[v].push_back(u); 18 } 19 } 20 21 int r1[maxn],num1; 22 int r2[maxn],num2; 23 int r3[maxn],num3; 24 int md; 25 stack <int> s; 26 void print(int now){ 27 int pla = now; 28 while(dep[pla] != to) r1[++num1] = pla,pla = fa[pla]; 29 r1[++num1] = pla; 30 31 pla = md; 32 while(dep[pla] != dep[now]) s.push(pla),pla = fa[pla]; 33 s.push(pla); 34 while(!s.empty()){r2[++num2] = s.top();s.pop();} 35 r2[++num2] = r1[num1]; 36 37 pla = wh[now]; 38 while(dep[pla] != dep[now]) s.push(pla),pla = fa[pla]; 39 s.push(pla); 40 while(!s.empty()){r3[++num3] = s.top();s.pop();} 41 pla = r1[num1]; 42 while(dep[pla] != up[now]) s.push(pla),pla = fa[pla]; 43 s.push(pla); 44 while(!s.empty()){r3[++num3] = s.top();s.pop();} 45 46 printf("%d %d\n",r1[1],r1[num1]); 47 printf("%d ",num1);for(int i=1;i<=num1;i++) printf("%d ",r1[i]); 48 puts(""); 49 printf("%d ",num2);for(int i=1;i<=num2;i++) printf("%d ",r2[i]); 50 puts(""); 51 printf("%d ",num3);for(int i=1;i<=num3;i++) printf("%d ",r3[i]); 52 puts("");flag = 1; 53 } 54 55 void dfs(int now,int dp){ 56 dep[now] = dp; 57 for(int i=0;i<g[now].size();i++){ 58 int nxt = g[now][i]; 59 if(fa[now] == nxt) continue; 60 if(flag) break; 61 if(dep[nxt] == 0){ 62 fa[nxt] = now; 63 dfs(nxt,dp+1); if(flag) break; 64 if(up[nxt] >= dep[now]) continue; 65 if(up[now] >= 10000000) up[now] = up[nxt],wh[now] = wh[nxt]; 66 else{ 67 if(up[now] <= up[nxt]){ 68 from = now; to = up[nxt];md = wh[nxt]; 69 }else { 70 from = now; to = up[now];up[now] = up[nxt]; 71 md = wh[now];wh[now]= wh[nxt]; 72 } 73 print(from); 74 } 75 }else{ 76 if(dep[nxt] > dep[now]) continue; 77 if(up[now] >= 10000000) up[now] = dep[nxt],wh[now] = now; 78 else{ 79 if(up[now] <= dep[nxt]){ 80 from = now; to = dep[nxt];md = now; 81 }else { 82 from = now; to = up[now];up[now] = dep[nxt]; 83 md = wh[now];wh[now] = now; 84 } 85 print(from); 86 } 87 } 88 } 89 } 90 91 void work(){ 92 flag = 0; from = 0; to = 0; num1 = num2 = num3 = 0; 93 for(int i=0;i<=n;i++) wh[i] = 0,fa[i] = 0,dep[i] = 0,up[i] = 1e9; 94 for(int i=1;i<=n;i++) if(!dep[i]) dfs(i,1); 95 if(!flag){puts("-1");} 96 } 97 98 int main(){ 99 int cas; scanf("%d",&cas); 100 while(cas--){ 101 read(); 102 work(); 103 } 104 return 0; 105 }