hdu5215 求无向图中是否有奇环和偶环 :lca+dfs使图->树
队友给的思路,感觉思路很好啊==
对图进行dfs扫描,假设u->v,遇到已经扫过的点v,计算当前点u和v的lca,lca和u以及v之间形成了一个环(计算奇偶)
这样只能计算有没有简单的奇偶环,比如两个简单的奇环在一起就成了偶环(无论两个奇环共享几条边)
所以在dfs中扫完子树之后,看有没有找到过两个奇环,如果奇环>=4就有了一个偶环(双向边,等价于两个奇环)
具体实现可以见代码==
1 #pragma comment(linker, "/STACK:102400000,102400000") 2 #include<stdio.h> 3 #include<string.h> 4 #include<algorithm> 5 #define maxn 100005 6 #define maxm 600005 7 using namespace std; 8 int Now,Next[maxm],Head[maxm],Point[maxm]; 9 int parent[maxn][25],depth[maxn]; 10 int ans1,ans2,vis[maxn]; 11 void Add(int u,int v) 12 { 13 Next[++Now]=Head[u]; 14 Head[u]=Now; 15 Point[Now]=v; 16 } 17 void dfs1(int u,int pre,int deep) 18 { 19 vis[u]=1; 20 parent[u][0]=pre; 21 depth[u]=deep; 22 for (int i=Head[u];i;i=Next[i]) 23 { 24 int v=Point[i]; 25 if (v==pre||vis[v]) continue; 26 dfs1(v,u,deep+1); 27 } 28 } 29 void double_build(int n) 30 { 31 int i,j; 32 for (i=0;i<20;i++) 33 for (j=1;j<=n;j++) 34 if (parent[j][i]<=0) parent[j][i+1]=0; 35 else parent[j][i+1]=parent[parent[j][i]][i]; 36 } 37 int lca(int u,int v) 38 { 39 int i; 40 if (depth[u]>depth[v]) swap(u,v); 41 for (i=0;i<=20;i++) 42 if ((depth[v]-depth[u])>>i&1) 43 v=parent[v][i]; 44 if (u==v) return u; 45 for (i=20;i>=0;i--) 46 if (parent[u][i]!=parent[v][i]) 47 { 48 u=parent[u][i]; 49 v=parent[v][i]; 50 } 51 return parent[u][0]; 52 } 53 void solve(int u,int v) 54 { 55 int fa=lca(u,v); 56 int tmp=depth[u]+depth[v]-2*depth[fa]+1; 57 if (tmp%2) ans1++; 58 else ans2++; 59 } 60 void dfs2(int u,int pre) 61 { 62 int i,v; 63 vis[u]=1; 64 for (i=Head[u];i;i=Next[i]) 65 { 66 v=Point[i]; 67 if (v==pre) continue; 68 if (vis[v]) solve(u,v); 69 else dfs2(v,u); 70 } 71 if (ans1>=4) ans2++; //thinking 72 } 73 int main() 74 { 75 int T,n,m,i,u,v,odd,even; 76 scanf("%d",&T); 77 while (T--) 78 { 79 scanf("%d%d",&n,&m); 80 Now=0; 81 memset(Head,0,sizeof(Head)); 82 for (i=1;i<=m;i++) 83 { 84 scanf("%d%d",&u,&v); 85 Add(u,v); Add(v,u); 86 } 87 memset(parent,0,sizeof(parent)); 88 memset(vis,0,sizeof(vis)); 89 for (i=1;i<=n;i++) 90 if (!vis[i]) dfs1(i,0,1); 91 double_build(n); 92 memset(vis,0,sizeof(vis)); 93 odd=even=0; 94 for (i=1;i<=n;i++) 95 if (!vis[i]) 96 { 97 ans1=ans2=0; 98 dfs2(i,0); 99 odd=max(odd,ans1); 100 even=max(even,ans2); 101 if (odd&&even) break; 102 } 103 if (odd) printf("YES\n"); 104 else printf("NO\n"); 105 if (even) printf("YES\n"); 106 else printf("NO\n"); 107 } 108 return 0; 109 }
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5215
--------------------------华丽分割---------------------
蛤蛤这方法是错的==
我就是来卖个萌明天两门祝不全挂