图论之各种找环
给我们一个有向图,找出长度为3的环,如果有的话,输出环上的三个点,如果没有,输出-1
因为只有三个点,所以可以暴力, 枚举两条边,判断第三条是不是存在即可。 fa -> u, u -> i, 判断g[i][fa]==1?
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #include <string.h> 5 #include <math.h> 6 #include <vector> 7 #include <string> 8 #include <vector> 9 #include <set> 10 #include <map> 11 #include <queue> 12 #include <stack> 13 #include <algorithm> 14 #include <functional> 15 using namespace std; 16 17 const int N = 5000 + 10; 18 char g[N][N]; 19 bool vis[N]; 20 int n; 21 int a,b,c; 22 void dfs(int u, int fa) 23 { 24 vis[u] = true; 25 for(int i=1; i<=n&&(!a||!b||!c);++i) 26 { 27 if(g[u][i]==0) continue; 28 if(fa!=-1 && g[i][fa]==1) 29 { 30 a = fa; 31 b = u; 32 c = i; 33 } 34 if(!vis[i]) 35 dfs(i,u); 36 } 37 } 38 int main() 39 { 40 41 while(scanf("%d",&n)!=EOF) 42 { 43 for(int i=1;i<=n;++i) 44 { 45 scanf("%s",g[i]+1); 46 for(int j=1;j<=n;++j) 47 g[i][j] -= '0'; 48 49 } 50 memset(vis,0,sizeof(vis)); 51 a = b = c = 0; 52 for(int i=1;i<=n;++i) 53 if(!vis[i]) 54 dfs(i,-1); 55 if(!a) 56 printf("%d\n",-1); 57 else 58 printf("%d %d %d\n",a,b,c); 59 60 } 61 return 0; 62 }
有向图找出所有的环,并输出(找的同时就能判断是奇偶环,也能找到最大的环)
利用是否存在后向边来判断,
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #include <string.h> 5 #include <math.h> 6 #include <vector> 7 #include <string> 8 #include <vector> 9 #include <set> 10 #include <map> 11 #include <queue> 12 #include <stack> 13 #include <algorithm> 14 #include <functional> 15 using namespace std; 16 17 const int N = 5000 + 10; 18 vector<int> g[N]; 19 int st[N],instack[N],mark[N],top; 20 void dfs(int u) 21 { 22 instack[u] = true; 23 mark[u] = true;//因为可能不联通,所以需要没有mark过的点,需要再次调用dfs 24 st[++top] = u; 25 for(int i=0;i<g[u].size(); ++i) 26 { 27 int v = g[u][i]; 28 if(!instack[v]) 29 dfs(v); 30 else 31 { 32 33 int t; 34 for(t=top;st[t]!=v;--t);//在栈中找到环的起始点 35 printf("%d:",top-t+1);//这这里就能判断是奇数环还是偶数环 36 for(int j=t;j<=top;++j) 37 printf("%d ",st[j]); 38 puts(""); 39 } 40 } 41 instack[u] = false; 42 top--; 43 } 44 void init(int n) 45 { 46 for(int i=1;i<=n;++i) 47 { 48 g[i].clear(); 49 instack[i] = mark[i] = 0; 50 } 51 top = 0; 52 } 53 int main() 54 { 55 int n,m; 56 while(scanf("%d%d",&n,&m)!=EOF) 57 { 58 init(n); 59 int u,v; 60 for(int i=1;i<=m;++i) 61 { 62 scanf("%d%d",&u,&v); 63 g[u].push_back(v); 64 } 65 for(int i=1;i<=n;++i) 66 if(!mark[i]) 67 dfs(i); 68 } 69 return 0; 70 }
各种找环
START————————————————————————
无向图判断是否存在环
topoSort变种,将度<=1的点入队列,如果最后没有将所有的点入过队列,那么久存在环
无向图找长度为奇数或者长度为偶数的环。
首先,我们找到所有的点双联通分量,那么每个分量里面的点都在环上。那么而判断环是奇环还是偶环可以用二分图染色来判断,如果是奇环,那么肯定不是二分图,反之是偶环。
有向图判断是否存在环
即判断是否是dag,可以用topoSort,复杂度O(E),也可以用dfs,如果存在后向边,那么就存在环,如果当前点有指向在栈中结点的边,那么就是后向边。
有向图找出所有的环并输出,能找到最大环,也能判断奇偶环