poj3259 最短路判环

题意:有一些点、一些道路和一些虫洞,道路是双向的,连接两点,花费正的时间,而虫洞是单向的,连接两点,可以使时间倒退,求是否能够回到过去。

只要明确回到过去其实就是当出现一个负环的时候,不断沿这个环走,就能够实现时间倒退了。

然后就是判负环……

spfa版:

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<queue>
 4 using namespace std;
 5 
 6 int head[505],next[6000],point[6000],val[6000],size;
 7 int n,dis[505],t[505];
 8 bool vis[505];
 9 
10 void add(int a,int b,int v){
11     int i;
12     for(i=head[a];~i;i=next[i]){
13         if(point[i]==b){
14             if(val[i]>v)val[i]=v;
15             return;
16         }
17     }
18     point[size]=b;
19     val[size]=v;
20     next[size]=head[a];
21     head[a]=size++;
22 }
23 
24 void spfa(int s){
25     memset(vis,0,sizeof(vis));
26     memset(dis,0x3f,sizeof(dis));
27     memset(t,0,sizeof(t));
28     queue<int>q;
29     dis[s]=0;
30     q.push(s);
31     vis[s]=1;
32     t[s]++;
33     int i;
34     bool f=1;
35     while(!q.empty()&&f){
36         int u=q.front();
37         q.pop();
38         vis[u]=0;
39         for(i=head[u];~i;i=next[i]){
40             int j=point[i];
41             if(dis[j]>dis[u]+val[i]){
42                 dis[j]=dis[u]+val[i];
43                 q.push(j);
44                 t[j]++;
45                 vis[j]=1;
46                 if(t[j]>n)f=0;
47             }
48         }
49     }
50     if(f)printf("NO
");
51     else printf("YES
");
52 }
53 
54 int main(){
55     int f;
56     while(scanf("%d",&f)!=EOF){
57         for(int q=1;q<=f;q++){
58             int w,m,i;
59             scanf("%d%d%d",&n,&m,&w);
60             memset(head,-1,sizeof(head));
61             size=0;
62             for(i=1;i<=m;i++){
63                 int a,b,v;
64                 scanf("%d%d%d",&a,&b,&v);
65                 add(a,b,v);
66                 add(b,a,v);
67             }
68             for(i=1;i<=w;i++){
69                 int a,b,v;
70                 scanf("%d%d%d",&a,&b,&v);
71                 add(a,b,-v);
72             }
73             spfa(1);
74         }
75     }
76     return 0;
77 }
View Code

bellman-fold版:

 1 #include<stdio.h>
 2 #include<string.h>
 3 
 4 int head[505],next[6000],point[6000],val[6000],size=0;
 5 int a,b,v,dis[505],n;
 6 
 7 void add(int a,int b,int v){
 8     int i;
 9     for(i=head[a];~i;i=next[i]){
10         if(point[i]==b){
11             if(val[i]>v)val[i]=v;
12             return;
13         }
14     }
15     point[size]=b;
16     val[size]=v;
17     next[size]=head[a];
18     head[a]=size++;
19 }
20 
21 void bf(int s){
22     int i,j,k;
23     memset(dis,0x3f,sizeof(dis));
24     dis[s]=0;
25     for(i=1;i<=n-1;i++){
26         for(j=1;j<=n;j++){
27             for(k=head[j];~k;k=next[k]){
28                 int p=point[k];
29                 if(dis[p]>dis[j]+val[k]){
30                     dis[p]=dis[j]+val[k];
31                 }
32             }
33         }
34     }
35     bool f=0;
36     for(i=1;i<=n;i++){
37         for(j=head[i];~j;j=next[j]){
38             int p=point[j];
39             if(dis[p]>dis[i]+val[j]){
40                 f=1;
41             }
42         }
43     }
44     if(f)printf("YES
");
45     else printf("NO
");
46 }
47 
48 int main(){
49     int f;
50     while(scanf("%d",&f)!=EOF){
51         for(int q=1;q<=f;q++){
52             int m,w;
53             scanf("%d%d%d",&n,&m,&w);
54             size=0;
55             memset(head,-1,sizeof(head));
56             int i;
57             for(i=1;i<=m;i++){
58                 scanf("%d%d%d",&a,&b,&v);
59                 add(a,b,v);
60                 add(b,a,v);
61             }
62             for(i=1;i<=w;i++){
63                 scanf("%d%d%d",&a,&b,&v);
64                 add(a,b,-v);
65             }
66             bf(1);
67         }
68     }
69     return 0;
70 }
View Code
原文地址:https://www.cnblogs.com/cenariusxz/p/4785131.html