UVA 558 Wormholes
要问是否存在一个总权重为负数的环,用dfs即可解决。
time:33ms
1 #include <cstdio> 2 #include <cstring> 3 #define N 3000 4 using namespace std; 5 int n, m, T, w[N], u[N], v[N], next[N], first[N], pa[N], d[N], tag, i; 6 7 void read_graph(void) 8 { 9 for(int e = 0; e < m; e++) 10 { 11 scanf("%d%d%d",&u[e], &v[e], &w[e]); 12 next[e] = first[u[e]]; 13 first[u[e]] = e; 14 } 15 } 16 void dfs(int x, int fa, int dis) 17 { 18 pa[x] = fa; 19 d[x] = dis; 20 for(int e = first[x]; e != -1; e = next[e]) 21 if(tag) return; 22 else if(pa[v[e]] == -1)//这里应该改为pa[v[e]] != x ,要考虑到负权上的点可能事先被访问过,感谢提出 23 { 24 if(v[e] == i && d[x] + w[e] < 0) 25 { 26 puts("possible"), tag = 1; 27 return ; 28 } 29 if(v[e] == i) 30 continue; 31 dfs(v[e], x, d[x] + w[e]); 32 } 33 } 34 int main(void) 35 { 36 scanf("%d", &T); 37 while(T--) 38 { 39 memset(first, -1, sizeof(first)); 40 tag = 0; 41 scanf("%d%d", &n, &m); 42 read_graph(); 43 for(i = 0; i < n; i++) 44 { 45 memset(d, 0, sizeof(d)), memset(pa, -1, sizeof(pa)), 46 dfs(i, -1, 0); 47 if(tag) 48 break; 49 } 50 if(!tag) 51 puts("not possible"); 52 } 53 return 0; 54 }
或者采用bellman—ford算法判断负权回路,
第n次循环时,若d[y]>d[x] + w[i],也就是能够继续松弛下去说明图中存在负权回路。
time:44ms速度还慢了一点,相比dfs
1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <algorithm> 5 #define INF 0x0f0f0f0f 6 #define MAXN 1111 7 #define MAXM 2222 8 using namespace std; 9 10 int d[MAXN]; 11 int u[MAXM], v[MAXM], w[MAXM], next[MAXM], first[MAXM]; 12 int t, n, m, e; 13 void read_graph(void) 14 { 15 scanf("%d%d",&n, &m); 16 for(e = 0; e < m; e++) 17 { 18 scanf("%d%d%d",&u[e], &v[e], &w[e]); 19 next[e] = first[u[e]]; 20 first[u[e]] = e; 21 } 22 } 23 void bellman_ford(void) 24 { 25 int i; 26 for(int k = 0; k < n-1; k++) 27 for(i = 0; i < e; i++ ) 28 { 29 int x = u[i], y = v[i]; 30 if(d[x] < INF) 31 d[y] = min(d[y], d[x] + w[i]); 32 } 33 for(i = 0; i < e; i++) 34 { 35 int x = u[i], y = v[i]; 36 if(d[y] > d[x] + w[i]) 37 { 38 puts("possible"); 39 break; 40 } 41 } 42 if(i == e) 43 puts("not possible"); 44 } 45 int main(void) 46 { 47 scanf("%d",&t); 48 while(t--) 49 { 50 memset(d, 0x0f, sizeof(d)); 51 memset(first, -1, sizeof(first)); 52 d[0] = 0; 53 read_graph(); 54 bellman_ford(); 55 } 56 return 0; 57 }
然后是spfa算法求解是否存在负权回路,通过判断顶点出队次数大于顶点数n,可知存在负权路,源点的time[0]应该初始化为1,其他的点每松弛一次,次数增加。
time:77ms竟然比bellman—ford,自己写的dfs倒是成了最快的了。
1 #include <cstdio> 2 #include <cstring> 3 #include <queue> 4 #include <vector> 5 #define MAXN 1111 6 #define MAXM 2222 7 using namespace std; 8 9 struct edgeType{ 10 int v, w; 11 edgeType(int a, int b):v(a), w(b){} 12 }; 13 int n,m,t; 14 int time[MAXN], inq[MAXN], d[MAXN]; 15 16 vector <edgeType> g[MAXN]; 17 18 bool spfa(void) 19 { 20 queue <int> q; 21 time[0] = 1; 22 q.push(0); 23 inq[0] = 1; 24 while(!q.empty()) 25 { 26 int x = q.front(); 27 q.pop(); 28 inq[x] = 0; 29 for(int i = 0; i < (int)g[x].size(); i++) 30 if(d[g[x][i].v] > d[x] + g[x][i].w) 31 { 32 d[g[x][i].v] = d[x] + g[x][i].w; 33 time[g[x][i].v]++; 34 if(time[g[x][i].v] == n + 1) 35 return false; 36 if(!inq[g[x][i].v]) 37 { 38 q.push(g[x][i].v); 39 inq[g[x][i].v] = 1; 40 } 41 } 42 } 43 return true; 44 } 45 int main(void) 46 { 47 scanf("%d", &t); 48 while(t--) 49 { 50 scanf("%d%d", &n, &m); 51 int a, b, c; 52 memset(time, 0, sizeof(time)); 53 memset(inq, 0,sizeof(inq)); 54 memset(d, 0x0f,sizeof(d)); 55 d[0] = 0; 56 for(int i = 0; i < MAXN; i++) 57 g[i].clear(); 58 for(int i = 0; i < m;i++) 59 { 60 scanf("%d%d%d", &a, &b, &c); 61 g[a].push_back(edgeType(b, c)); 62 } 63 if(spfa()) 64 puts("not possible"); 65 else puts("possible"); 66 } 67 return 0; 68 }