拓扑排序O(E), bellman O(VE) , 使用邻接表的dfs O(V+E) ,floyd O(N*N*N)
bellman算法只能判断是否存在负环。
所以可以先把权值全部设为-1
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include <stdio.h> 2 #include <string.h> 3 #include <vector> 4 #include <stack> 5 using namespace std; 6 const int N = 10000 + 10; 7 const int INF = 1<<30; 8 struct node 9 { 10 int u,v,weight; 11 }g[N+N]; 12 int dist[N]; 13 inline int max(const int &a, const int &b) 14 { 15 return a < b ? b : a; 16 } 17 18 void init(int n) 19 { 20 for(int i=0; i<=n; ++i) 21 { 22 23 dist[i] = INF; 24 } 25 } 26 27 void relax(int u, int v, int weight) 28 { 29 if(dist[v] > dist[u] + weight) 30 dist[v] = dist[u] + weight; 31 } 32 bool bell(int n, int m) 33 { 34 int i,j; 35 for(i=1; i<n; ++i) 36 for(j=0; j<m; ++j) 37 relax(g[j].u,g[j].v,g[j].weight); 38 39 for(i=0; i<m; ++i) 40 if(dist[g[i].v] > dist[g[i].u] +g[i].weight) 41 return true; 42 return false; 43 } 44 int main() 45 { 46 int n,m,i,u,v; 47 while(scanf("%d%d",&n,&m)!=EOF) 48 { 49 if(n==0 && m==0) 50 break; 51 init(n); 52 for(i=0; i<m; ++i) 53 { 54 scanf("%d%d",&g[i].u,&g[i].v); 55 g[i].weight = -1;//把权值全部改为负的,然后判断是不是存在负环 56 if(g[i].u==0) 57 dist[g[i].v] = -1; 58 } 59 if(bell(n,m)) 60 puts("NO"); 61 else 62 puts("YES"); 63 } 64 }
枚举起点进行dfs,如果能遇到顶点和起点相同,则存在环
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include <stdio.h> 2 #include <string.h> 3 #include <vector> 4 #include <stack> 5 using namespace std; 6 const int N = 10000 + 10; 7 vector<int> g[N]; 8 int start; 9 bool vis[N],flag; 10 void dfs(int u) 11 { 12 if(flag) 13 return; 14 for(int i=0;i<g[u].size(); ++i) 15 { 16 int v = g[u][i]; 17 if(v==start) 18 { 19 flag = true;//有环 20 return; 21 } 22 if(!vis[v]) 23 { 24 vis[v] = true; 25 dfs(v); 26 } 27 } 28 } 29 int main() 30 { 31 int n,m,i,u,v; 32 while(scanf("%d%d",&n,&m)!=EOF) 33 { 34 if(n==0 && m==0) 35 break; 36 for(i=0; i<n; ++i) 37 g[i].clear(); 38 for(i=0; i<m; ++i) 39 { 40 scanf("%d%d",&u,&v); 41 g[u].push_back(v); 42 } 43 flag = false; 44 for(i=0; i<n; ++i) 45 { 46 memset(vis,0,sizeof(vis)); 47 vis[i] = true; 48 start = i; 49 dfs(i); 50 if(flag) 51 break; 52 } 53 if(flag) 54 puts("NO"); 55 else 56 puts("YES"); 57 } 58 }
拓扑排序如果能生成n个顶点序列,那么说明是GAG图
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include <stdio.h> 2 #include <string.h> 3 #include <vector> 4 #include <stack> 5 using namespace std; 6 const int N = 10000 + 10; 7 vector<int> g[N]; 8 stack<int> st; 9 int in[N],add[N],cnt; 10 inline int max(const int &a, const int &b) 11 { 12 return a < b ? b : a; 13 } 14 void topSort(int n, int m) 15 { 16 int u,i; 17 for(i=1; i<=n; ++i) 18 if(in[i]==0) 19 st.push(i); 20 while(!st.empty()) 21 { 22 u = st.top(); 23 cnt++; 24 st.pop(); 25 for(i=0; i<g[u].size(); ++i) 26 { 27 --in[g[u][i]]; 28 if(in[g[u][i]]==0) 29 st.push(g[u][i]); 30 31 32 } 33 } 34 } 35 void init(int n) 36 { 37 cnt = 0; 38 for(int i=1; i<=n; ++i) 39 { 40 g[i].clear(); 41 add[i] = in[i] = 0; 42 } 43 } 44 int main() 45 { 46 int n,m,i,u,v; 47 while(scanf("%d%d",&n,&m)!=EOF) 48 { 49 if(n==0 && m==0) 50 break; 51 init(n); 52 for(i=0; i<m; ++i) 53 { 54 scanf("%d%d",&u,&v); 55 u++; 56 v++; 57 g[u].push_back(v); 58 in[v]++; 59 } 60 topSort(n,m); 61 if(cnt==n)//能生成n个顶点的序列,说明是DAG图 62 { 63 puts("YES"); 64 } 65 else 66 puts("NO"); 67 } 68 }