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 }

                                                                 

原文地址:https://www.cnblogs.com/rootial/p/3297994.html