[kuangbin带你飞]专题四 最短路练习

Til the Cows Come HomePOJ - 2387

题意:给你一幅地图,点1~N,双向正权路,问你N到1的最短路径?

算法:Dijkstra或者SPFA

思路:因为是正权路径,可以用Dijkstra算法;SPFA区别就是可以判断负权环。

 1 #include <iostream>
 2 #include <vector>
 3 #include <cstring>
 4 #include <algorithm>
 5 #include <queue>
 6 #include <cstdio>
 7 #include <map>
 8 #include <math.h>
 9 
10 using namespace std;
11 
12 const int INF = 0x3f3f3f3f;
13 const int MAXN = 1000+10;
14 
15 struct qnode{
16     int v,c;
17     qnode(int _v=0,int _c=0):v(_v),c(_c) {}
18     bool operator < (const qnode &r)const{
19         return c>r.c;
20     }
21 };
22 struct Edge{
23     int v,cost;
24     Edge(int _v=0,int _cost=0):v(_v),cost(_cost) {}
25 };
26 vector<Edge>E[MAXN];
27 void addedge(int u,int v,int w){E[u].push_back(Edge(v,w));}
28 bool vis[MAXN];
29 int dist[MAXN];
30 void Dijkstra(int n,int start){
31     memset(vis,false,sizeof vis);
32     for(int i=1;i<=n;i++) dist[i]=INF;
33     priority_queue<qnode> q;
34     dist[start]=0;
35     q.push(qnode(start,0));
36     while(!q.empty()){
37         qnode tmp = q.top();q.pop();
38         int u = tmp.v;
39         if(vis[u]) continue;
40         vis[u]=true;
41         for(int i=0;i<E[u].size();i++){
42             int v = E[u][i].v , cost = E[u][i].cost;
43             if(!vis[v]&&dist[v]>dist[u]+cost){
44                 dist[v] = dist[u] + cost;
45                 q.push(qnode(v,dist[v]));
46             }
47         }
48     }
49 }
50 int main()
51 {
52     int T,N;
53     cin>>T>>N;
54     while(T--){
55         int a,b,c;cin>>a>>b>>c;
56         addedge(a,b,c) , addedge(b,a,c);
57     }
58     Dijkstra(N,1);
59     cout<<dist[N]<<endl;
60     return 0;
61 }
Dijkstra
 1 #include <iostream>
 2 #include <vector>
 3 #include <cstring>
 4 #include <algorithm>
 5 #include <queue>
 6 #include <cstdio>
 7 #include <map>
 8 #include <math.h>
 9 
10 using namespace std;
11 
12 const int INF = 0x3f3f3f3f;
13 const int MAXN = 1000+10;
14 
15 struct Edge{
16     int v,cost;
17     Edge(int _v=0,int _cost=0):v(_v),cost(_cost) {}
18 };
19 vector<Edge> E[MAXN];
20 void addedge(int u,int v,int w){E[u].push_back(Edge(v,w));}
21 bool vis[MAXN];
22 int cnt[MAXN],dis[MAXN];
23 bool SPFA(int start,int n){
24     memset(vis,false,sizeof vis);
25     for(int i=1;i<=n;i++) dis[i] = INF;
26     vis[start]=true,dis[start]=0;
27     queue<int> q;q.push(start);
28     memset(cnt,0,sizeof cnt);cnt[start] = 1;
29     while(q.size()){
30         int u = q.front();q.pop();
31         vis[u]=false;
32         for(int i=0;i<E[u].size();i++){
33             int v = E[u][i].v;
34             if(dis[v]>dis[u]+E[u][i].cost){
35                 dis[v]=dis[u]+E[u][i].cost;
36                 if(!vis[v]){
37                     vis[v] = true;
38                     q.push(v);
39                     if(++cnt[v]>n) return false;
40                 }
41             }
42         }
43     }
44     return true;
45 }
46 int main()
47 {
48     int T,N;
49     cin>>T>>N;
50     while(T--){
51         int a,b,c;cin>>a>>b>>c;
52         addedge(a,b,c) , addedge(b,a,c);
53     }
54     SPFA(1,N);
55     cout<<dis[N]<<endl;
56     return 0;
57 }
SPFA


FroggerPOJ - 2253

题意:青蛙想要从石头1跳到石头2;其他石头是编号3~n;起点为石头1,终点石头2;问你们从起点到终点,跳到最大距离的最小可能是多少?

算法:SPFA

思路:这里只要改变路径改变方式就行了,dist[i]变成从起点到该点i途中,最大跳跃距离;

 1 #include <iostream>
 2 #include <vector>
 3 #include <cstring>
 4 #include <algorithm>
 5 #include <queue>
 6 #include <cstdio>
 7 #include <map>
 8 #include <math.h>
 9 #include <iomanip>
10 
11 using namespace std;
12 
13 const int INF = 0x3f3f3f3f;
14 const int MAXN = 200+10;
15 
16 struct node{
17     int x,y;
18     node(int a,int b):x(a),y(b) {}
19     node() {}
20     int d(int a,int b){
21         a = a - x , b = b - y;
22         return a*a + b*b;
23     }
24 }po[MAXN];
25 bool vis[MAXN];
26 int dis[MAXN];
27 bool SPFA(int start,int n){
28     memset(vis,false,sizeof vis);
29     for(int i=1;i<=n;i++) dis[i] = INF;
30     vis[start]=true,dis[start]=0;
31     queue<int> q;q.push(start);
32     while(q.size()){
33         int u = q.front();q.pop();
34         vis[u]=false;
35         for(int i=1;i<=n;i++){
36             if(i==u) continue;
37             int d = max( dis[u] , po[u].d(po[i].x , po[i].y));
38             if(dis[i]>d){
39                 dis[i]=d;
40                 if(!vis[i]){
41                     vis[i] = true;
42                     q.push(i);
43                 }
44             }
45         }
46     }
47     return true;
48 }
49 int main()
50 {
51     int n,cas=1;
52     while(cin>>n&&n){
53         cout<<"Scenario #"<<cas++<<endl;
54         cout<<"Frog Distance = ";
55         for(int i=1;i<=n;i++) cin>>po[i].x>>po[i].y;
56         SPFA(1,n);
57         double r = dis[2];
58         cout<<fixed<<setprecision(3)<<sqrt(r)<<endl;
59         cout<<endl;
60     }
61     return 0;
62 }
View Code


Heavy Transportation POJ - 1797

题意:一个地图,双向路径,权值为路径的最大承重量,顾客问你从地点1到地点n,允许最大承重重量为多少?

算法:SPFA或者最小生成树

思路:这题和上一题很像,但是这里求最大,所以反过来就行了;思路2:就是将所有的路径从大到小排序,然后一个个路径进行路径联通,如果有路径相连的,就通过最小生成树,归为一棵树,如果整个地图都变成一棵树,那么最后的路径为最小路径即最大允许承重;

 1 #include <iostream>
 2 #include <vector>
 3 #include <cstring>
 4 #include <algorithm>
 5 #include <queue>
 6 #include <cstdio>
 7 #include <map>
 8 #include <math.h>
 9 
10 using namespace std;
11 
12 const int INF = 0x3f3f3f3f;
13 const int MAXN = 1000+10;
14 
15 struct Edge{
16     int v,cost;
17     Edge(int _v=0,int _cost=0):v(_v),cost(_cost) {}
18 };
19 vector<Edge> E[MAXN];
20 void addedge(int u,int v,int w){E[u].push_back(Edge(v,w));}
21 bool vis[MAXN];
22 int cnt[MAXN],dis[MAXN];
23 bool SPFA(int start,int n){
24     memset(vis,false,sizeof vis);
25     for(int i=1;i<=n;i++) dis[i] = 0;
26     vis[start]=true,dis[start]=INF;
27     queue<int> q;q.push(start);
28     memset(cnt,0,sizeof cnt);cnt[start] = 1;
29     while(q.size()){
30         int u = q.front();q.pop();
31         vis[u]=false;
32         for(int i=0;i<E[u].size();i++){
33             int v = E[u][i].v;
34             int d = min(dis[u], E[u][i].cost);
35             if(dis[v]<d){
36                 dis[v]=d;
37                 if(!vis[v]){
38                     vis[v] = true;
39                     q.push(v);
40                     if(++cnt[v]>n) return false;
41                 }
42             }
43         }
44     }
45     return true;
46 }
47 int main()
48 {
49     int _,cas=1;cin>>_;
50     while(_--){
51         int n,m;
52         cin>>n>>m;
53         for(int i=1;i<=n;i++) E[i].clear();
54         while(m--){
55             int a,b,c;cin>>a>>b>>c;
56             addedge(a,b,c) , addedge(b,a,c);
57         }
58         SPFA(1,n);
59         cout<<"Scenario #"<<cas++<<":"<<endl;
60         cout<<dis[n]<<endl;
61         cout<<endl;
62     }
63     return 0;
64 }
SPFA
 1 #include <iostream>
 2 #include <vector>
 3 #include <cstring>
 4 #include <algorithm>
 5 #include <queue>
 6 #include <cstdio>
 7 #include <map>
 8 #include <math.h>
 9 
10 using namespace std;
11 
12 const int INF = 0x3f3f3f3f;
13 const int MAXN = 1000+10;
14 
15 struct Edge{
16     int u,v,cost;
17     Edge(int a,int b,int c):u(a),v(b),cost(c){}
18     bool operator <(const Edge &a)const {
19         return cost > a.cost;
20     }
21 };
22 vector<Edge>E;
23 int fa[MAXN];
24 int FFa(int x){
25     if(fa[x]==x) return x;
26     return fa[x]=FFa(fa[x]);
27 }
28 bool check(int n){
29     if(FFa(1)==FFa(n)) return true;
30     return false;
31 }
32 int solve(int n){
33     for(int i=1;i<=n;i++) fa[i] = i;
34     for(int i=0;i<E.size();i++){
35         int u = E[i].u , v = E[i].v , w = E[i].cost;
36         int uFa = FFa(u) , vFa = FFa(v);
37         if(uFa==vFa) continue;
38         fa[vFa] = uFa;
39         if(check(n)) return w;
40     }
41 }
42 int main()
43 {
44     int _,cas=1;cin>>_;
45     while(_--){
46         E.clear();
47         int n,m;
48         cin>>n>>m;
49         while(m--){
50             int a,b,c;cin>>a>>b>>c;
51             E.push_back(Edge(a,b,c));
52         }
53         sort(E.begin(),E.end());
54         cout<<"Scenario #"<<cas++<<":"<<endl;
55         cout<<solve(n)<<endl;
56         cout<<endl;
57     }
58     return 0;
59 }
最小生成树


Silver Cow Party POJ - 3268

题意:有n个农村(编号从1开始),每个农村只有一头牛,农村之间是单向正权路径,party举办农村题目给出,每头牛都需要从自己农村出发到派对,然后从派对回到自己农村,问这n头牛中的最大最短路径。

算法:SPFA

思路:做最短路径,想要看点,编号是多少到多少;第二看路,是单向还是双向?正权?非负权?有负权?(负权就存在负环);第三就是问题;这题很简单,分两段,从所属地到派对地(这里反过来求,路径也反过来存)、从派对地到所属地;然后所有牛的最短路径,来回加起来找最大就行了。

 1 #include <iostream>
 2 #include <vector>
 3 #include <cstring>
 4 #include <algorithm>
 5 #include <queue>
 6 #include <cstdio>
 7 #include <map>
 8 #include <math.h>
 9 
10 using namespace std;
11 
12 const int INF = 0x3f3f3f3f;
13 const int MAXN = 1000+10;
14 
15 struct Edge{
16     int v,cost;
17     Edge(int _v=0,int _cost=0):v(_v),cost(_cost) {}
18 };
19 vector<Edge> E1[MAXN],E2[MAXN];
20 void addedge1(int u,int v,int w){E1[u].push_back(Edge(v,w));}
21 void addedge2(int u,int v,int w){E2[u].push_back(Edge(v,w));}
22 bool vis[MAXN];
23 int cnt[MAXN],dis1[MAXN],dis2[MAXN];
24 bool SPFA(int start,int n,vector<Edge> E[MAXN],int (&dis)[MAXN]){
25     memset(vis,false,sizeof vis);
26     for(int i=1;i<=n;i++) dis[i] = INF;
27     vis[start]=true,dis[start]=0;
28     queue<int> q;q.push(start);
29     memset(cnt,0,sizeof cnt);cnt[start] = 1;
30     while(q.size()){
31         int u = q.front();q.pop();
32         vis[u]=false;
33         for(int i=0;i<E[u].size();i++){
34             int v = E[u][i].v;
35             if(dis[v]>dis[u]+E[u][i].cost){
36                 dis[v]=dis[u]+E[u][i].cost;
37                 if(!vis[v]){
38                     vis[v] = true;
39                     q.push(v);
40                     if(++cnt[v]>n) return false;
41                 }
42             }
43         }
44     }
45     return true;
46 }
47 int main()
48 {
49     int n,m,x;cin>>n>>m>>x;
50     while(m--){
51         int a,b,c;cin>>a>>b>>c;
52         addedge1(a,b,c);addedge2(b,a,c);
53     }
54     int ans = 0;
55     SPFA(x,n,E1,dis1);
56     SPFA(x,n,E2,dis2);
57     for(int i=1;i<=n;i++) ans = max(ans,dis1[i]+dis2[i]);
58     cout<<ans<<endl;
59     return 0;
60 }
View Code


 Currency Exchange POJ - 1860

题意:货币交易AtoB,交易汇率RAB,手续费CAB;( A - CAB ) * RAB = B;现在你有某种货币某量(货币种类从1~N),给一些货币之间的兑换方式;问你是否存在通过兑换货币的方式,使得你原来的某种货币变多;

算法:SPFA

思路:这里货币兑换,我通过案例,数学公式模拟,只要兑换数量超过阈值就不会亏,稳赚;这里按照题目,模拟全额向外兑换扩散,dist数组:全额兑换到这种货币最大数量;这里只要兑换会初始货币就YES了

 1 #include <iostream>
 2 #include <vector>
 3 #include <cstring>
 4 #include <algorithm>
 5 #include <queue>
 6 #include <cstdio>
 7 #include <map>
 8 #include <math.h>
 9 
10 using namespace std;
11 
12 const int INF = 0x3f3f3f3f;
13 const int MAXN = 1000+10;
14 
15 struct Edge{
16     int v;
17     double rate,cost;
18     Edge(int _v=0,double _rate=0,double _cost=0):v(_v),rate(_rate),cost(_cost) {}
19 };
20 vector<Edge> E[MAXN];
21 void addedge(int u,int v,double r,double w){E[u].push_back(Edge(v,r,w));}
22 bool vis[MAXN];
23 double dis[MAXN];
24 bool SPFA(int n,int start,double vv){
25     memset(vis,false,sizeof vis);
26     for(int i=1;i<=n;i++) dis[i] = 0;
27     vis[start]=true,dis[start]=vv;
28     queue<int> q;q.push(start);
29     while(q.size()){
30         int u = q.front();q.pop();
31         vis[u]=false;
32         for(int i=0;i<E[u].size();i++){
33             int v = E[u][i].v;
34             double d = (dis[u] - E[u][i].cost)*E[u][i].rate;
35             if(dis[v]<d){
36                 dis[v]=d;
37                 if(v==start) return true;
38                 if(!vis[v]){
39                     vis[v] = true;
40                     q.push(v);
41                 }
42             }
43         }
44     }
45     return false;
46 }
47 int main()
48 {
49     int n,m;
50     double s,v;
51     cin>>n>>m>>s>>v;
52     while(m--){
53         int a,b;
54         double c,d,e,f;
55         cin>>a>>b>>c>>d>>e>>f;
56         addedge(a,b,c,d);addedge(b,a,e,f);
57     }
58     if(SPFA(n,s,v)) puts("YES");
59     else puts("NO");
60     return 0;
61 }
SPFA


Wormholes POJ - 3259

题意:起点:1 ,N个点;双向正权路径;虫洞为单向负权路径,权值为时间;问能否将时间倒退1000s(多少秒不重要,有负环就可行)。

算法:SPFA

思路:这里因为有负权,需要判断负环;这题和上一题很像,dis数组:维护到达这点的最小时间;只要从起点开始回到起点就YES,或者存在负环也YES;

 1 #include <iostream>
 2 #include <vector>
 3 #include <cstring>
 4 #include <algorithm>
 5 #include <queue>
 6 #include <cstdio>
 7 #include <map>
 8 #include <math.h>
 9 
10 using namespace std;
11 
12 const int INF = 0x3f3f3f3f;
13 const int MAXN = 500+10;
14 
15 struct Edge{
16     int v,cost;
17     Edge(int _v=0,int _cost=0):v(_v),cost(_cost) {}
18 };
19 vector<Edge> E[MAXN];
20 void addedge(int u,int v,int w){E[u].push_back(Edge(v,w));}
21 bool vis[MAXN];
22 int cnt[MAXN],dis[MAXN];
23 bool SPFA(int start,int n){
24     memset(vis,false,sizeof vis);
25     for(int i=1;i<=n;i++) dis[i] = INF;
26     vis[start]=true,dis[start]=0;
27     queue<int> q;q.push(start);
28     memset(cnt,0,sizeof cnt);cnt[start] = 1;
29     while(q.size()){
30         int u = q.front();q.pop();
31         vis[u]=false;
32         for(int i=0;i<E[u].size();i++){
33             int v = E[u][i].v;
34             if(dis[v]>dis[u]+E[u][i].cost){
35                 dis[v]=dis[u]+E[u][i].cost;
36                 if(v==start) return true;
37                 if(!vis[v]){
38                     vis[v] = true;
39                     q.push(v);
40                     if(++cnt[v]>n) return true;
41                 }
42             }
43         }
44     }
45     return false;
46 }
47 int main()
48 {
49     int _;cin>>_;
50     while(_--){
51         int n,m,w;cin>>n>>m>>w;
52         for(int i=1;i<=n;i++) E[i].clear();
53         while(m--){
54             int a,b,c;cin>>a>>b>>c;
55             addedge(a,b,c);addedge(b,a,c);
56         }
57         while(w--){
58             int a,b,c;cin>>a>>b>>c;
59             addedge(a,b,-c);
60         }
61         if(SPFA(1,n)) puts("YES");
62         else puts("NO");
63     }
64     return 0;
65 }
SPFA


 MPI Maelstrom POJ - 1502 

题意:n台计算机;每台计算机都可以互相通信;用一个矩阵表示通信成本,自身通信成本为0,计算机a到计算机b的成本和计算机b到计算机a的成本一样,所以输入只给了必要的矩阵出来;这里注意输入就行了;从计算机1开始向外通信扩展,问到所有计算机都收到信息的最小时间成本;

算法:SPFA

 1 #include <iostream>
 2 #include <vector>
 3 #include <cstring>
 4 #include <algorithm>
 5 #include <queue>
 6 #include <cstdio>
 7 #include <map>
 8 #include <math.h>
 9 
10 using namespace std;
11 
12 const int INF = 0x3f3f3f3f;
13 const int MAXN = 100+10;
14 
15 struct Edge{
16     int v,cost;
17     Edge(int _v=0,int _cost=0):v(_v),cost(_cost) {}
18 };
19 vector<Edge> E[MAXN];
20 void addedge(int u,int v,int w){E[u].push_back(Edge(v,w));}
21 bool vis[MAXN];
22 int cnt[MAXN],dis[MAXN];
23 bool SPFA(int start,int n){
24     memset(vis,false,sizeof vis);
25     for(int i=1;i<=n;i++) dis[i] = INF;
26     vis[start]=true,dis[start]=0;
27     queue<int> q;q.push(start);
28     memset(cnt,0,sizeof cnt);cnt[start] = 1;
29     while(q.size()){
30         int u = q.front();q.pop();
31         vis[u]=false;
32         for(int i=0;i<E[u].size();i++){
33             int v = E[u][i].v;
34             if(dis[v]>dis[u]+E[u][i].cost){
35                 dis[v]=dis[u]+E[u][i].cost;
36                 if(v==start) return true;
37                 if(!vis[v]){
38                     vis[v] = true;
39                     q.push(v);
40                     if(++cnt[v]>n) return true;
41                 }
42             }
43         }
44     }
45     return false;
46 }
47 int main()
48 {
49     int n;
50     while(cin>>n&&n){
51         for(int i=1;i<=n;i++)
52             for(int j=1;j<i;j++){
53                 char ch = getchar();while(ch==' '||ch=='\n') ch=getchar();
54                 if(ch=='x') continue;
55                 int a=0;
56                 do{
57                     a*=10;a+=ch-'0';
58                     ch=getchar();
59                 }while(ch<='9'&&ch>='0');
60                 //cout<<a<<endl;
61                 addedge(i,j,a);addedge(j,i,a);
62             }
63         SPFA(1,n);
64         int ans = 0;for(int i=1;i<=n;i++) ans = max(ans,dis[i]);
65         cout<<ans<<endl;
66     }
67     return 0;
68 }
View Code


 Cow ContestPOJ - 3660 

题意:n头牛有m个上下关系,单向的;根据这个关系排序,能确定排序位置的牛有多少个?

算法:Bellman_ford

思路:一开始是把所有路径记录,然后求一个公共前缀的,但是想想好像不对,因为如果已经确定前面和后面明确有多少个,那它也是确定排序位置的,相当于快排每一步,确定一个数位置一样;关键点:如果一个数确定位置了,那么确定它前面的点和后面的点总共等于n-1;这里用B_F算法求两两点最短距离,这题比较特殊,因为他们的边就是一种单向关系,dis[i][j] 和 dis[j][i]不可能同时存在,并且dis向后推的距离只会越来越大,不可能连接的就永远INF;如果dis数组不是INF,就表示两点之间是联通的,那么这两个点之间的关系是确定的;

 1 #include <iostream>
 2 #include <vector>
 3 #include <cstring>
 4 #include <algorithm>
 5 #include <queue>
 6 #include <cstdio>
 7 #include <map>
 8 #include <math.h>
 9 
10 using namespace std;
11 
12 const int INF = 0x3f3f3f3f;
13 const int MAXN = 100+10;
14 
15 int n,m,dis[MAXN][MAXN];
16 
17 void bellman_ford(){
18     for(int k=1;k<=n;k++)
19         for(int i=1;i<=n;i++)
20             for(int j=1;j<=n;j++)
21                 if(dis[i][j]>dis[i][k]+dis[k][j]) dis[i][j] = dis[i][k] + dis[k][j];
22 }
23 
24 int main()
25 {
26     cin>>n>>m;
27     memset(dis,INF,sizeof dis);
28     while(m--){
29         int a,b;cin>>a>>b;
30         dis[a][b] = 1;
31     }
32     bellman_ford();
33     int res[MAXN] = {0};
34     for(int i=1;i<=n;i++)
35         for(int j=1;j<i;j++) if(dis[i][j]!=INF||dis[j][i]!=INF) res[i]++,res[j]++;
36     int ans = 0;
37     for(int i=1;i<=n;i++) if(res[i]==n-1) ans++;
38     cout<<ans<<endl;
39     return 0;
40 }
View Code


 Arbitrage POJ - 2240 

题意:给你货币种类和货币汇率,问你是否存在通过货币兑换获利的方法?

算法:SPFA

思路:和前面一道题差不多,起点从1到n,依次进入SPFA,如果能回到起点就能获利;

 1 #include <iostream>
 2 #include <vector>
 3 #include <cstring>
 4 #include <algorithm>
 5 #include <queue>
 6 #include <cstdio>
 7 #include <map>
 8 #include <math.h>
 9 #include <sstream>
10 #include <stdlib.h>
11 
12 using namespace std;
13 
14 const int INF = 0x3f3f3f3f;
15 const int MAXN = 30+10;
16 
17 map<string,int> mp;
18 
19 struct Edge{
20     int v;
21     double cost;
22     Edge(int _v=0,double _cost=0):v(_v),cost(_cost) {}
23 };
24 vector<Edge> E[MAXN];
25 void addedge(int u,int v,double w){E[u].push_back(Edge(v,w));}
26 bool vis[MAXN];
27 int cnt[MAXN];
28 double dis[MAXN];
29 bool SPFA(int start,int n){
30     memset(vis,false,sizeof vis);
31     for(int i=1;i<=n;i++) dis[i] = 0;
32     vis[start]=true,dis[start]=1;
33     queue<int> q;q.push(start);
34     memset(cnt,0,sizeof cnt);cnt[start] = 1;
35     while(q.size()){
36         int u = q.front();q.pop();
37         vis[u]=false;
38         for(int i=0;i<E[u].size();i++){
39             int v = E[u][i].v;
40             if(dis[v]<dis[u]*E[u][i].cost){
41                 //cout<<u<<" "<<v<<" "<<dis[u]<<" "<<dis[v]<<" "<<dis[u]*E[u][i].cost<<" "<<E[u][i].cost<<endl;
42                 dis[v]=dis[u]*E[u][i].cost;
43                 if(v==start) return true;
44                 if(!vis[v]){
45                     vis[v] = true;
46                     q.push(v);
47                     if(++cnt[v]>n) return true;
48                 }
49             }
50         }
51     }
52     return false;
53 }
54 
55 
56 int main()
57 {
58     int n,m,cas=1;
59     while(cin>>n&&n){
60         cout<<"Case "<<cas++<<": ";
61         mp.clear();
62         for(int i=1;i<=n;i++){
63             E[i].clear();
64             string s;cin>>s;
65             mp[s]=i;
66         }
67         cin>>m;
68         while(m--){
69             int a,b;
70             double c;
71             for(int i=0;i<3;i++){
72                 string s;cin>>s;
73                 char ss[100];
74                 strcpy(ss,s.c_str());
75                 if(i==0) a = mp[s];
76                 else if(i==1) c = atof(ss);
77                 else b = mp[s];
78             }
79             //cout<<a<<" "<<b<<" "<<c<<endl;
80             addedge(a,b,c);
81         }
82         bool flag = true;
83         for(int i=1;i<=n&&flag;i++){
84             if(SPFA(i,n)) flag=false;
85         }
86         if(flag) puts("No");
87         else puts("Yes");
88     }
89     return 0;
90 }
View Code


 Invitation CardsPOJ - 1511

题意:点1是巴士总站,其余有n-1个站,每个n-1站点派一个人,给出路线,路线花费金额,问所有人从总站到站点再回总站的总费用最低为多少?

算法:SPFA

思路:这题,前面的一道题(牛参加派对)差不多;就是求一个站点1为起点的SPFA;然后逆序路径,求站点1为终点的SPFA;

易错点:路径用vector,每一次都需要clear(),容易超时,这里换个路径存储方式减少时间;然后不要用cin输入,用scanf;

 1 #include <iostream>
 2 #include <vector>
 3 #include <cstring>
 4 #include <algorithm>
 5 #include <queue>
 6 #include <cstdio>
 7 #include <map>
 8 #include <math.h>
 9 
10 using namespace std;
11 
12 const int INF = 0x3f3f3f3f;
13 const int MAXN = 1000000+10;
14 
15 struct Edge{
16     int v,cost,next;
17 };
18 Edge E1[MAXN],E2[MAXN];
19 int head1[MAXN],head2[MAXN],num1,num2;
20 void addedge(int u,int v,int w){
21     E1[num1].v = v , E1[num1].cost = w , E1[num1].next = head1[u] , head1[u] = num1++;
22     E2[num2].v = u , E2[num2].cost = w , E2[num2].next = head2[v] , head2[v] = num2++;
23 }
24 bool vis[MAXN];
25 int dis1[MAXN],dis2[MAXN];
26 bool SPFA(int start,int n,Edge E[MAXN],int head[MAXN],int (&dis)[MAXN]){
27     memset(vis,false,sizeof vis);
28     for(int i=1;i<=n;i++) dis[i] = INF;
29     vis[start]=true,dis[start]=0;
30     queue<int> q;q.push(start);
31     while(q.size()){
32         int u = q.front();q.pop();
33         vis[u]=false;
34         for(int i=head[u];i!=-1;i=E[i].next){
35             int v = E[i].v;
36             if(dis[v]>dis[u]+E[i].cost){
37                 dis[v]=dis[u]+E[i].cost;
38                 if(!vis[v]){
39                     vis[v] = true;
40                     q.push(v);
41                 }
42             }
43         }
44     }
45     return true;
46 }
47 int main()
48 {
49     int _;
50     //cin>>_;
51     scanf("%d",&_);
52     while(_--){
53         int n,m;
54         //cin>>n>>m;
55         scanf("%d%d",&n,&m);
56         num1 = num2 = 0;
57         memset(head1,-1,sizeof head1);memset(head2,-1,sizeof head2);
58         while(m--){
59             int a,b,c;
60             //cin>>a>>b>>c;
61             scanf("%d%d%d",&a,&b,&c);
62             addedge(a,b,c);
63         }
64         long long  ans = 0;
65         SPFA(1,n,E1,head1,dis1);
66         SPFA(1,n,E2,head2,dis2);
67         for(int i=1;i<=n;i++) ans += (dis1[i]+dis2[i]);
68         cout<<ans<<endl;
69     }
70     return 0;
71 }
View Code


 CandiesPOJ - 3159 

题意:班级有n个学生,进行分糖果,每个同学有个单向关系,(a,b,c):同学b的糖果 要小于等于(同学a的糖果+c);问满足所有关系的条件下,学生1与学生n之间最大糖果差是多少?

算法:差分约束 + dij / SPFA(栈)

思路:差分约束就是,每两个点之间关系是不等式,所有关系要转变成一个方向,最大值要小于等于求最短;最大值要大于等于求最长;然后这题求最短路径可以用DIJKSTRA算法,也可以用SPFA,但是这题用队列的话会TLE,用栈就能过;

我并没有用数据考察过,目前就只能这么理解;

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <queue>
 5 
 6 using namespace std;
 7 
 8 const int MAXN = 30000 + 10;
 9 const int MAXM = 150000 + 10;
10 const int INF = 0x3f3f3f3f;
11 
12 struct Edge{int v,cost,next;}E[MAXM];
13 int head[MAXN],num;
14 void addedge(int u,int v,int w){E[num].v = v , E[num].cost = w , E[num].next = head[u] , head[u] = num++;}
15 
16 struct node{
17     int u,cost;
18     node(int a,int b):u(a),cost(b) {};
19     bool operator < (const node &a)const{
20         return cost > a.cost;
21     }
22 };
23 bool vis[MAXN];
24 int dist[MAXN];
25 void Dijkstra(int start,int n){
26     memset(vis,false,sizeof vis);
27     memset(dist,INF,sizeof dist);dist[start] = 0;
28     priority_queue<node> q;q.push(node(start,0));
29     while(q.size()){
30         node p = q.top();q.pop();
31         int u = p.u;
32         if(vis[u]) continue;
33         vis[u] = true;
34         for(int i = head[u];i != -1;i = E[i].next){
35             int v = E[i].v , cost  = E[i].cost;
36             if(dist[v] > dist[u] + cost){
37                 dist[v] = dist[u] + cost;
38                 q.push(node(v,dist[v]));
39             }
40         }
41     }
42 }
43 
44 int main(){
45     int n,m;scanf("%d%d",&n,&m);
46     num=0;memset(head,-1,sizeof head);
47     while(m--){
48         int a,b,c;scanf("%d%d%d",&a,&b,&c);
49         addedge(a,b,c);
50     }
51     Dijkstra(1,n);
52     cout<<dist[n]<<endl;
53 }
Dijkstra
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <queue>
 5 #include <stack>
 6 
 7 using namespace std;
 8 
 9 const int MAXN = 30000 + 10;
10 const int MAXM = 150000 + 10;
11 const int INF = 0x3f3f3f3f;
12 
13 struct Edge{int v,cost,next;}E[MAXM];
14 int head[MAXN],num;
15 void addedge(int u,int v,int w){E[num].v = v , E[num].cost = w , E[num].next = head[u] , head[u] = num++;}
16 
17 bool vis[MAXN];
18 int dist[MAXN],cnt[MAXN];
19 bool SPFA(int start,int n){
20     memset(vis,false,sizeof vis);vis[start] = true;
21     memset(dist,INF,sizeof dist);dist[start] = 0;
22     memset(cnt,0,sizeof cnt);cnt[start] = 1;
23     stack<int> q;q.push(start);
24     while(q.size()){
25         int u = q.top();q.pop();
26         vis[u] = false;
27         for(int i = head[u];i != -1;i = E[i].next){
28             int v = E[i].v, cost = E[i].cost;
29             if(dist[v] > dist[u] + cost){
30                 dist[v] = dist[u] + cost;
31                 if(vis[v]) continue;
32                 vis[v] = true;
33                 q.push(v);
34                 if(++cnt[v]>n) return false;
35             }
36         }
37     }
38     return true;
39 }
40 
41 int main(){
42     int n,m;scanf("%d%d",&n,&m);
43     num=0;memset(head,-1,sizeof head);
44     while(m--){
45         int a,b,c;scanf("%d%d%d",&a,&b,&c);
46         addedge(a,b,c);
47     }
48     SPFA(1,n);
49     cout<<dist[n]<<endl;
50 }
SPFA(栈)


 SubwayPOJ - 2502

 题意:一个帅小伙搬到大城市住,上学都坐地铁了,所有点都是坐标表示,距离以米为单位,步行速度是10km/h,地铁都是双向的,速度为40km/h,点1是家,点2是学校,问从家到学校最短时间是多少?

算法:DIJKSTRA

思路:就存地铁的边,然后在遍历所有任意两点之间的距离存起来,然后跑一遍dij算法

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <string.h>
  5 #include <queue>
  6 #include <vector>
  7 #include <stack>
  8 #include <cmath>
  9 #include <map>
 10 #include <limits.h>
 11 #include <float.h>
 12 
 13 using namespace std;
 14 
 15 const int MAXN = 200 + 10;
 16 const double INF = 0x3f3f3f3f;
 17 
 18 struct Edge{
 19     int v;
 20     double cost;
 21     Edge(int a,double b):v(a),cost(b) {}
 22 };
 23 vector<Edge> E[MAXN];
 24 void addedge(int u,int v,double w){E[u].push_back(Edge(v,w));E[v].push_back(Edge(u,w));}
 25 
 26 bool vis[MAXN];
 27 double dist[MAXN];
 28 struct qnode{
 29     int v;
 30     double cost;
 31     qnode(int a,double b):v(a),cost(b) {}
 32     bool operator < (const qnode &a)const{
 33         return cost > a.cost;
 34     }
 35 };
 36 void Dijkstra(int start,int n){
 37     memset(vis,false,sizeof vis);
 38     for(int i=0;i<n;i++) dist[i] = DBL_MAX;
 39     dist[start] = 0;
 40     priority_queue<qnode> q;q.push(qnode(start,0));
 41     while(q.size()){
 42         qnode p = q.top();q.pop();
 43         int u = p.v;
 44         if(vis[u]) continue;
 45         vis[u] = true;
 46         //cout<<u<<" "<<dist[u]<<endl;
 47         for(int i = 0;i < E[u].size();i++){
 48             int v = E[u][i].v;
 49             if(vis[v]) continue;
 50             if(dist[v]>dist[u]+E[u][i].cost){
 51                 dist[v] = dist[u] + E[u][i].cost;
 52                 q.push(qnode(v,dist[v]));
 53             }
 54         }
 55     }
 56 }
 57 
 58 double getDis(int _a,int _b,int _c,int _d){
 59     double a = _a, b = _b , c = _c , d = _d;
 60     a/=1000 , b/=1000 , c/=1000 , d/=1000;
 61     double ans = (a-c)*(a-c)+(b-d)*(b-d);
 62     return sqrt(ans);
 63 }
 64 
 65 
 66 int main(){
 67     int num = 0;
 68     map<pair<int,int>,int> mp;
 69     int nx[MAXN] , ny[MAXN];
 70     int x,y;
 71     scanf("%d%d",&x,&y);nx[num]=x,ny[num]=y,mp[make_pair(x,y)] = num++;
 72     scanf("%d%d",&x,&y);nx[num]=x,ny[num]=y;
 73     if(mp.find(make_pair(x,y))!=mp.end()){puts("0");return 0;}mp[make_pair(x,y)] = num++;
 74     while(scanf("%d%d",&x,&y)!=EOF){
 75         int faNum;
 76         if(mp.find(make_pair(x,y))==mp.end()){
 77             nx[num] = x;ny[num] = y;mp[make_pair(x,y)] = num;faNum = num++;
 78         }else faNum = mp[make_pair(x,y)];
 79         while(1){
 80             int a,b;scanf("%d%d",&a,&b);
 81             if(a==-1&&b==-1) break;
 82             int suNum;
 83             if(mp.find(make_pair(a,b))==mp.end()){
 84                 nx[num] = a;ny[num] = b;mp[make_pair(a,b)] = num;suNum = num++;
 85             }else suNum = mp[make_pair(a,b)];
 86             //cout<<faNum<<" "<<suNum<<" "<<getDis(x,y,a,b)/40*60<<endl;
 87             addedge(suNum,faNum,getDis(x,y,a,b)/40*60);
 88             x = a, y = b,faNum = suNum;
 89         }
 90     }
 91     for(int i=0;i<num;i++){
 92         x = nx[i] , y = ny[i];
 93         for(int j=i+1;j<num;j++){
 94             int a = nx[j] , b = ny[j];
 95             addedge(i,j,getDis(x,y,a,b)/10*60);
 96             //cout<<i<<" "<<j<<" "<<x<<" "<<y<<" "<<a<<" "<<b<<" "<<getDis(x,y,a,b)/10*60<<endl;
 97         }
 98     }
 99     Dijkstra(0,num);
100     printf("%.0f\n",dist[1]);
101 }
DIJKSTRA


 昂贵的聘礼POJ - 1062 

题意:需要娶妻,但是不够钱,女方告诉你,你如果可以拿到某某物件,彩礼可以降至多少钱?然后你就开始了一个以物易物的道路,重点在于,存在一个m,只要你跟等级为x的人交易了,就不能跟等级和x差距超过m的人交易了。

算法:BFS

思路:这题看似最短路径,其实要考虑区间,其实是BFS;这里每个点存一个编号,一个区间、一个当前交易路径累积金额;答案要加一个当前物品的价值;这里如果需要剪枝,可以进行dis【当前节点编号】【left】【right】大小进行判重。我就没有进行判重,直接把所有可能性都跑一遍;然后我这里也是预先假设没有环的,再加上路径权都是非负数。

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <string.h>
  5 #include <queue>
  6 #include <vector>
  7 #include <stack>
  8 #include <cmath>
  9 #include <map>
 10 #include <limits.h>
 11 #include <float.h>
 12 
 13 #define sc scanf
 14 #define pf printf
 15 #define REP(i,a,b) for(int i=(a);i<(b);i++)
 16 #define CLR(x,m) memset(x,m,sizeof x);
 17 #define LOCAL freopen("test.txt","r",stdin)
 18 #define UCCU ios::sync_with_stdio(0);
 19 #define XSD(i) cout << fixed << setprecision(i);
 20 #define pii pair<int,int>
 21 #define xx first
 22 #define yy second
 23 
 24 using namespace std;
 25 
 26 typedef long long LL;
 27 typedef unsigned long long ULL;
 28 typedef double DB;
 29 typedef long double LDB;
 30 
 31 const double eps = 1e-8;
 32 //const int inf = 1<<30;
 33 const int INF = 0x3f3f3f3f;
 34 const long long llinf = (long long)300100*1000000000;
 35 const DB PI = acos(-1.0);
 36 const LL mod = 1e9+7;
 37 
 38 //-----------------------------------------------------------------------
 39 const int MAXN = 100 + 10;
 40 
 41 int n,m;
 42 
 43 int level[MAXN],value[MAXN];
 44 struct Edge{
 45     int v,cost;
 46     Edge(int a,int b):v(a),cost(b) {}
 47 };
 48 vector<Edge> E[MAXN];
 49 void addedge(int u,int v,int cost){E[u].push_back(Edge(v,cost));}
 50 bool checkLR(int index,int left,int right){
 51     return (left<=level[index]&&level[index]<=right);
 52 }
 53 
 54 struct node{
 55     int now, left , right, dis;
 56     node(int a,int l,int r,int d):now(a),left(l),right(r),dis(d) {};
 57 };
 58 LL ans;
 59 void SPFA(){
 60     int left = level[1] - m;if(left<0) left = 0;
 61     int right = level[1] + m;
 62     ans = value[1];//cout<<ans<<endl;
 63     queue<node> q;
 64     q.push(node(1,left, right, 0));
 65 
 66     while(q.size()){
 67         node p = q.front();q.pop();
 68         //cout<<"----------------------------------"<<endl;
 69         //cout<<p.now<<" "<<p.left<<" "<<p.right<<" "<<p.dis<<endl;
 70         int u = p.now;
 71         for(int i=0;i<E[u].size();i++){
 72             int v = E[u][i].v;
 73             if(!checkLR(v,p.left,p.right)) continue;
 74             int dis = p.dis + E[u][i].cost;
 75             if(p.dis + value[p.now] < dis ) continue;
 76             if(ans < dis) continue;
 77             int l = level[v] - m; if(l < 0 ) l = 0;
 78             int r = level[v] + m;
 79             if(p.left>l) l = p.left;
 80             if(p.right<r) r = p.right;
 81             if(ans>dis + value[v]) ans = dis + value[v];//cout<<ans<<endl;}
 82             //cout<<v<<" "<<l<<" "<<r<<" "<<dis<<endl;
 83             q.push(node(v,l,r,dis));
 84         }
 85     }
 86 }
 87 
 88 
 89 
 90 void init(){
 91     cin>>m>>n;
 92     for(int i=1;i<=n;i++){
 93         int x;cin>>value[i]>>level[i]>>x;
 94         for(int j=0;j<x;j++){
 95             int a,b;cin>>a>>b;
 96             addedge(i,a,b);
 97         }
 98     }
 99 }
100 
101 int main(){
102     //LOCAL;
103     UCCU;
104     init();
105     SPFA();
106     cout<<ans<<endl;
107     return 0;
108 }
View Code


 N - TramPOJ - 1847

题意:N个岔路,给你两个岔路点A,B;问从A到B最少操作数是多少?每个岔路都只能走一个方向到一个特定的岔路,但是你可以通过一个操作改变方向到另一个岔路。如果不操作就能从A到B,答案为0;

算法:SPFA/DIJ

思路:这里关键在于建边,初始边的权值为0,其余皆为1;

易错点:这里无法到达,需要输出 -1

SPFA

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <string.h>
#include <queue>
#include <vector>
#include <stack>
#include <cmath>
#include <map>
#include <limits.h>
#include <float.h>

#define sc scanf
#define pf printf
#define REP(i,a,b) for(int i=(a);i<(b);i++)
#define CLR(x,m) memset(x,m,sizeof x);
#define LOCAL freopen("test.txt","r",stdin)
#define UCCU ios::sync_with_stdio(0);
#define XSD(i) cout << fixed << setprecision(i);
#define pii pair<int,int>
#define xx first
#define yy second

using namespace std;

typedef long long LL;
typedef unsigned long long ULL;
typedef double DB;
typedef long double LDB;

const double eps = 1e-8;
//const int inf = 1<<30;
const int INF = 0x3f3f3f3f;
const long long llinf = (long long)300100*1000000000;
const DB PI = acos(-1.0);
const LL mod = 1e9+7;

//-----------------------------------------------------------------------
const int MAXN = 100 + 10;

int n,a,b;

struct Edge{
    int v,cost;
    Edge(int a,int b):v(a),cost(b) {}
};
vector<Edge> E[MAXN];
void addedge(int u,int v,int cost){E[u].push_back(Edge(v,cost));}

int dis[MAXN];
bool vis[MAXN];
void SPFA(){
    memset(vis,false,sizeof vis);
    memset(dis,INF,sizeof dis);
    dis[a] = 0;
    vis[a] = true;
    queue<int> q;
    q.push(a);
    while(q.size()){
        int u = q.front();q.pop();
        vis[u] = false;
        for(int i = 0;i<E[u].size();i++){
            int v = E[u][i].v,cost = E[u][i].cost;
            if(dis[v] > dis[u] + cost){
                dis[v] = dis[u] + cost;
                if(vis[v]) continue;
                vis[v] = true;
                q.push(v);
            }
        }
    }
}



void init(){
    cin>>n>>a>>b;
    for(int i=1;i<=n;i++){
        int len;cin>>len;
        for(int j=0;j<len;j++){
            int c;cin>>c;
            if(j) addedge(i,c,1);
            else addedge(i,c,0);
        }
    }
}

int main(){
    //LOCAL;
    UCCU;
    init();
    SPFA();
    if(dis[b]==INF) puts("-1");
    else cout<<dis[b]<<endl;
    return 0;
}

DIJKSTRA

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <string.h>
#include <queue>
#include <vector>
#include <stack>
#include <cmath>
#include <map>
#include <limits.h>
#include <float.h>

#define sc scanf
#define pf printf
#define REP(i,a,b) for(int i=(a);i<(b);i++)
#define CLR(x,m) memset(x,m,sizeof x);
#define LOCAL freopen("test.txt","r",stdin)
#define UCCU ios::sync_with_stdio(0);
#define XSD(i) cout << fixed << setprecision(i);
#define pii pair<int,int>
#define xx first
#define yy second

using namespace std;

typedef long long LL;
typedef unsigned long long ULL;
typedef double DB;
typedef long double LDB;

const double eps = 1e-8;
//const int inf = 1<<30;
const int INF = 0x3f3f3f3f;
const long long llinf = (long long)300100*1000000000;
const DB PI = acos(-1.0);
const LL mod = 1e9+7;

//-----------------------------------------------------------------------
const int MAXN = 100 + 10;

int n,a,b;

struct Edge{
    int v,cost;
    Edge(int a,int b):v(a),cost(b) {}
};
vector<Edge> E[MAXN];
void addedge(int u,int v,int cost){E[u].push_back(Edge(v,cost));}

struct node{
    int v, c;
    node(int _v,int _c):v(_v),c(_c) {}
    bool operator <(const node &r)const{
        return c > r.c;
    }
};

bool vis[MAXN];
int dist[MAXN];

int DIJKSTRA(){
    memset(vis,false,sizeof vis);
    memset(dist,INF,sizeof dist);
    priority_queue<node> q;
    dist[a] = 0;q.push(node(a,0));
    while(q.size()){
        node tmp = q.top();q.pop();
        int u = tmp.v;
        if(u == b) return dist[b];
        if(vis[u]) continue;
        vis[u] = true;
        for(int i=0;i<E[u].size();i++){
            int v = E[u][i].v , cost = E[u][i].cost;
            if(!vis[v]&&dist[v] > dist[u] + cost){
                dist[v] = dist[u] + cost;
                q.push(node(v,dist[v]));
            }
        }
    }
    return -1;
}



void init(){
    cin>>n>>a>>b;
    for(int i=1;i<=n;i++){
        int len;cin>>len;
        for(int j=0;j<len;j++){
            int c;cin>>c;
            if(j) addedge(i,c,1);
            else addedge(i,c,0);
        }
    }
}

int main(){
    //LOCAL;
    UCCU;
    init();
    cout<<DIJKSTRA()<<endl;
    return 0;
}


Extended Traffic LightOJ - 1074 

题意:给你n个点,每个点有个拥堵值,m条单向边,权值为(目的拥堵值-出发拥堵值)的立方——因为是立方,所以存在负值边,存在负环;起点永远是点1,然后进行多次查询,每次输入目的点,求到目的点最短路径;如果路径值小于3或者无法到达输出?

算法:SPFA

思路:这里用SPFA求出,从起点1到所有点距离,一次SPFA就可以应对多次查询。

查看代码
 #include <iostream>
#include <cstdio>
#include <cstring>
#include <string.h>
#include <queue>
#include <vector>
#include <stack>
#include <cmath>
#include <map>
#include <limits.h>
#include <float.h>

#define sc scanf
#define pf printf
#define REP(i,a,b) for(int i=(a);i<(b);i++)
#define CLR(x,m) memset(x,m,sizeof x);
#define LOCAL freopen("test.txt","r",stdin)
#define UCCU ios::sync_with_stdio(0);
#define XSD(i) cout << fixed << setprecision(i);
#define pii pair<int,int>
#define xx first
#define yy second

using namespace std;

typedef long long LL;
typedef unsigned long long ULL;
typedef double DB;
typedef long double LDB;

const double eps = 1e-8;
//const int inf = 1<<30;
const int INF = 0x3f3f3f3f;
const long long llinf = (long long)300100*1000000000;
const DB PI = acos(-1.0);
const LL mod = 1e9+7;

//-----------------------------------------------------------------------
const int MAXN = 200 + 10;

struct Edge{
    int v,cost;
    Edge(int a,int b):v(a),cost(b) {}
};
vector<Edge> E[MAXN];
void addedge(int u,int v,int cost){E[u].push_back(Edge(v,cost));}

int n,m,k;
int level[MAXN];

bool vis[MAXN];
int dist[MAXN],cnt[MAXN];

bool SPFA(){
    memset(vis,false,sizeof vis);
    memset(dist,INF,sizeof dist);
    memset(cnt,0,sizeof cnt);
    queue<int> q;
    dist[1] = 0;vis[1]=true;cnt[1] = 1;
    q.push(1);
    while(q.size()){
        int u = q.front();q.pop();
        vis[u] = false;
        for(int i=0;i<E[u].size();i++){
            int v = E[u][i].v , cost = E[u][i].cost;
            if(dist[v] > dist[u] + cost){
                dist[v] = dist[u] + cost;
                if(vis[v]||cnt[v]>n-1) continue;
                vis[v] = true;
                q.push(v);
                ++cnt[v];
            }
        }
    }
    return true;
}

void init(){
    cin>>n;
    for(int i=1;i<=n;i++) {E[i].clear();cin>>level[i];}
    cin>>m;
    for(int i=0;i<m;i++){
        int a,b;cin>>a>>b;
        int c = level[b] - level[a];
        addedge(a,b,c*c*c);
    }
}

int main(){
    //LOCAL;
    UCCU;
    int _,cas = 1;cin>>_;
    while(_--){
        cout<<"Case "<<cas++<<":"<<endl;
        init();
        SPFA();
        cin>>k;
        while(k--){
            int a;cin>>a;
            if(dist[a]<3||dist[a]==INF||cnt[a]>n-1) cout<<"?"<<endl;
            else cout<<dist[a]<<endl;
        }
    }
    return 0;
}


The Shortest Path in Nya Graph HDU - 4725 

题意:给你n个点,多层地图,每一层可能包含多个点,或者没有点;邻层之间的点可以联通,代价为c;然后存在其他m条边连同不同层;

算法:dijkstra、spfa

难点:这里关键就是建图;每一层都新建一个点,这个点单向到自己这个层的代价为0;然后上下两层到这个点代价为c;

查看代码
 #include <iostream>
#include <cstdio>
#include <cstring>
#include <string.h>
#include <queue>
#include <vector>
#include <stack>
#include <cmath>
#include <map>
#include <limits.h>
#include <float.h>

#define sc scanf
#define pf printf
#define REP(i,a,b) for(int i=(a);i<(b);i++)
#define CLR(x,m) memset(x,m,sizeof x);
#define LOCAL freopen("test.txt","r",stdin)
#define UCCU ios::sync_with_stdio(0);
#define XSD(i) cout << fixed << setprecision(i);
#define pii pair<int,int>
#define xx first
#define yy second

using namespace std;

typedef long long LL;
typedef unsigned long long ULL;
typedef double DB;
typedef long double LDB;

const double eps = 1e-8;
//const int inf = 1<<30;
const int INF = 0x3f3f3f3f;
const long long llinf = (long long)300100*1000000000;
const DB PI = acos(-1.0);
const LL mod = 1e9+7;

//-----------------------------------------------------------------------
const int MAXN = 2*1e5 + 10;
const int MAXM = 5*1e5 + 10;

struct Edge{
    int v,cost;
    Edge(int a,int b):v(a),cost(b) {}
};
vector<Edge> E[MAXM];
void addedge(int u,int v,int cost){E[u].push_back(Edge(v,cost));}

struct node{
    int u,cost;
    node(int a,int b):u(a),cost(b) {};
    bool operator < (const node &a)const{
        return cost > a.cost;
    }
};

bool vis[MAXN],islayer[MAXN/2];
int dist[MAXN],layer[MAXN/2];
void Dijkstra(int start,int n){
    for(int i=1;i<=n+n;i++) vis[i]=false,dist[i]=INF;
    dist[start] = 0;
    priority_queue<node> q;q.push(node(start,0));
    while(q.size()){
        node p = q.top();q.pop();
        int u = p.u;
        if(vis[u]) continue;
        vis[u] = true;
        if(u == n) break;
        for(int i=0;i<E[u].size();i++){
            int v = E[u][i].v , cost  = E[u][i].cost;
            if(dist[v] > dist[u] + cost){
                dist[v] = dist[u] + cost;
                q.push(node(v,dist[v]));
            }
        }
    }
}

int n;

void init(){
    int m,c;
    scanf("%d%d%d",&n,&m,&c);
    for(int i=1;i<=n+n;i++){
        if(i<=n) islayer[i] = false;
        E[i].clear();
    }
    for(int i=1;i<=n;i++) {scanf("%d",&layer[i]);islayer[layer[i]]=true;}
    for(int i=1;i<=n;i++){
        int a = layer[i];
        addedge(n+a,i,0);
        if(a-1>=1&&islayer[a-1]) addedge(i,n+a-1,c);
        if(a+1<=n&&islayer[a+1]) addedge(i,n+a+1,c);
    }
    for(int i=0;i<m;i++){
        int a,b,d;scanf("%d%d%d",&a,&b,&d);
        addedge(a,b,d);addedge(b,a,d);
    }
}

int main(){
    //LOCAL;
    //UCCU;
    //cin.tie(0);
    //cout.tie(0);
    int _,cas = 1;
    scanf("%d",&_);
    while(_--){
        init();
        Dijkstra(1,n);
        int ans = dist[n]==INF?-1:dist[n];
        printf("Case #%d: %d\n",cas++,ans);
    }
    return 0;
}
查看代码
 #include <iostream>
#include <cstdio>
#include <cstring>
#include <string.h>
#include <queue>
#include <vector>
#include <stack>
#include <cmath>
#include <map>
#include <limits.h>
#include <float.h>

#define sc scanf
#define pf printf
#define REP(i,a,b) for(int i=(a);i<(b);i++)
#define CLR(x,m) memset(x,m,sizeof x);
#define LOCAL freopen("test.txt","r",stdin)
#define UCCU ios::sync_with_stdio(0);
#define XSD(i) cout << fixed << setprecision(i);
#define pii pair<int,int>
#define xx first
#define yy second

using namespace std;

typedef long long LL;
typedef unsigned long long ULL;
typedef double DB;
typedef long double LDB;

const double eps = 1e-8;
//const int inf = 1<<30;
const int INF = 0x3f3f3f3f;
const long long llinf = (long long)300100*1000000000;
const DB PI = acos(-1.0);
const LL mod = 1e9+7;

//-----------------------------------------------------------------------
const int MAXN = 2*1e5 + 10;
const int MAXM = 5*1e5 + 10;

struct Edge{int v,cost,next;}E[MAXM];
int head[MAXN],num;
void addedge(int u,int v,int cost){E[num].v = v,E[num].cost = cost,E[num].next = head[u],head[u]=num++;}

struct node{
    int u,cost;
    node(int a,int b):u(a),cost(b) {};
    bool operator < (const node &a)const{
        return cost > a.cost;
    }
};

bool vis[MAXN],islayer[MAXN/2];
int dist[MAXN],layer[MAXN/2];

void Dijkstra(int start,int n){
    memset(vis,false,sizeof vis);
    memset(dist,INF,sizeof dist);
    dist[start] = 0;
    priority_queue<node> q;q.push(node(start,0));
    while(q.size()){
        node p = q.top();q.pop();
        int u = p.u;
        if(vis[u]) continue;
        vis[u] = true;
        if(u == n) break;
        for(int i = head[u];i != -1;i = E[i].next){
            int v = E[i].v , cost  = E[i].cost;
            if(dist[v] > dist[u] + cost){
                dist[v] = dist[u] + cost;
                q.push(node(v,dist[v]));
            }
        }
    }
}

int n;

void init(){
    int m,c;
    //cin>>n>>m>>c;
    scanf("%d%d%d",&n,&m,&c);
    num = 0;
    for(int i=1;i<=n+n;i++){
        if(i<=n) islayer[i] = false;
        head[i] = -1;
    }
    for(int i=1;i<=n;i++) {
        //cin>>layer[i];
        scanf("%d",&layer[i]);
        islayer[layer[i]]=true;
    }
    for(int i=1;i<=n;i++){
        int a = layer[i];
        addedge(n+a,i,0);
        if(a-1>=1&&islayer[a-1]) addedge(i,n+a-1,c);
        if(a+1<=n&&islayer[a+1]) addedge(i,n+a+1,c);
    }
    for(int i=0;i<m;i++){
        int a,b,d;
        //cin>>a>>b>>d;
        scanf("%d%d%d",&a,&b,&d);
        addedge(a,b,d);addedge(b,a,d);
    }
}

int main(){
    //LOCAL;
    //UCCU;
    //cin.tie(0);
    //cout.tie(0);
    int _,cas = 1;
    //cin>>_;
    scanf("%d",&_);
    while(_--){
        init();
        Dijkstra(1,n);
        //cout<<"Case #"<<cas++<<": "<<dist[n]<<endl;
        int ans = dist[n]==INF?-1:dist[n];
        printf("Case #%d: %d\n",cas++,ans);
    }
    return 0;
}
查看代码
 #include <iostream>
#include <cstdio>
#include <cstring>
#include <string.h>
#include <queue>
#include <vector>
#include <stack>
#include <cmath>
#include <map>
#include <limits.h>
#include <float.h>

#define sc scanf
#define pf printf
#define REP(i,a,b) for(int i=(a);i<(b);i++)
#define CLR(x,m) memset(x,m,sizeof x);
#define LOCAL freopen("test.txt","r",stdin)
#define UCCU ios::sync_with_stdio(0);
#define XSD(i) cout << fixed << setprecision(i);
#define pii pair<int,int>
#define xx first
#define yy second

using namespace std;

typedef long long LL;
typedef unsigned long long ULL;
typedef double DB;
typedef long double LDB;

const double eps = 1e-8;
//const int inf = 1<<30;
const int INF = 0x3f3f3f3f;
const long long llinf = (long long)300100*1000000000;
const DB PI = acos(-1.0);
const LL mod = 1e9+7;

//-----------------------------------------------------------------------
const int MAXN = 2*1e5 + 10;
const int MAXM = 5*1e5 + 10;

struct Edge{
    int v,cost;
    Edge(int _v=0,int _cost=0):v(_v),cost(_cost) {}
};
vector<Edge> E[MAXN];
void addedge(int u,int v,int w){E[u].push_back(Edge(v,w));}

bool vis[MAXN];
int cnt[MAXN],dis[MAXN];

bool SPFA(int start,int n){
    memset(vis,false,sizeof vis);
    for(int i=1;i<=n+n;i++) dis[i] = INF;
    vis[start]=true,dis[start]=0;
    queue<int> q;q.push(start);
    memset(cnt,0,sizeof cnt);cnt[start] = 1;
    while(q.size()){
        int u = q.front();q.pop();
        vis[u]=false;
        for(int i=0;i<E[u].size();i++){
            int v = E[u][i].v;
            if(dis[v]>dis[u]+E[u][i].cost){
                dis[v]=dis[u]+E[u][i].cost;
                if(!vis[v]){
                    vis[v] = true;
                    q.push(v);
                    if(++cnt[v]>n) return false;
                }
            }
        }
    }
    return true;
}

int n;
bool islayer[MAXN/2];
int layer[MAXN/2];

void init(){
    int m,c;
    scanf("%d%d%d",&n,&m,&c);
    for(int i=1;i<=n+n;i++){
        if(i<=n) islayer[i] = false;
        E[i].clear();
    }
    for(int i=1;i<=n;i++) {scanf("%d",&layer[i]);islayer[layer[i]]=true;}
    for(int i=1;i<=n;i++){
        int a = layer[i];
        addedge(n+a,i,0);
        if(a-1>=1&&islayer[a-1]) addedge(i,n+a-1,c);
        if(a+1<=n&&islayer[a+1]) addedge(i,n+a+1,c);
    }
    for(int i=0;i<m;i++){
        int a,b,d;scanf("%d%d%d",&a,&b,&d);
        addedge(a,b,d);addedge(b,a,d);
    }
}

int main(){
    //LOCAL;
    //UCCU;
    //cin.tie(0);
    //cout.tie(0);
    int _,cas = 1;
    scanf("%d",&_);
    while(_--){
        init();
        SPFA(1,n);
        //for(int i=1;i<=n;i++) cout<<dis[i]<<endl;
        int ans = dis[n]==INF?-1:dis[n];
        printf("Case #%d: %d\n",cas++,ans);
    }
    return 0;
}


Marriage Match IVHDU - 3416 

题意:n个城市,m条道路,每条道路只能走一次,每条边有个费用c,给你一个起点s,终点t;然后男主角必须从s开始走最短路径(最小费用)到t,问有多少次机会,即存在多少条互不影响的最短路径;

算法:预处理+最大流

思路:这里我一开始用最小费用最大流,然后TLE;然后想到对于求最大流进行减枝预处理,类似于Destroying the bus stationsHDU - 2485这道题,把不符合答案的边剔除掉,只保留答案边。因为这里必须是最短路径,那就跑一次spfa,求出每个点到起点的距离,如果dis[u] + c ==dis[v],那么(u,v,c)这个边就是最短路径里的一条边,加入到最大流图里;然后跑一次最大流;

查看代码
 #include <iostream>
#include <cstdio>
#include <cstring>
#include <string.h>
#include <queue>
#include <vector>
#include <stack>
#include <cmath>
#include <map>
#include <limits.h>
#include <float.h>

#define sc scanf
#define pf printf
#define REP(i,a,b) for(int i=(a);i<(b);i++)
#define CLR(x,m) memset(x,m,sizeof x);
#define LOCAL freopen("test.txt","r",stdin)
#define UCCU ios::sync_with_stdio(0);
#define XSD(i) cout << fixed << setprecision(i);
#define pii pair<int,int>
#define xx first
#define yy second

using namespace std;

typedef long long LL;
typedef unsigned long long ULL;
typedef double DB;
typedef long double LDB;

const double eps = 1e-8;
//const int inf = 1<<30;
const int INF = 0x3f3f3f3f;
const long long llinf = (long long)300100*1000000000;
const DB PI = acos(-1.0);
const LL mod = 1e9+7;

//-----------------------------------------------------------------------
const int MAXN = 1000 + 10;
const int MAXM = 200000 + 10;
struct Edge{
    int to,next,cap,flow;
}edge[MAXM];
int tol,head[MAXN];
void init(){
    tol = 2;
    memset(head, -1, sizeof head);
}
void addedge(int u,int v,int w,int rw = 0){
    edge[tol].to = v;edge[tol].cap = w;edge[tol].flow = 0;
    edge[tol].next = head[u];head[u] = tol++;
    edge[tol].to = u;edge[tol].cap = rw;edge[tol].flow = 0;
    edge[tol].next = head[v];head[v] = tol++;
}
int Q[MAXN];
int dep[MAXN],cur[MAXN],sta[MAXN];
bool bfs(int s,int t,int n){
    int front = 0,tail = 0;
    memset(dep, -1, sizeof(dep[0])*(n+1));
    dep[s] = 0;
    Q[tail++] = s;
    while(front < tail){
        int u = Q[front++];
        for(int i = head[u];i != -1;i = edge[i].next){
            int v = edge[i].to;
            if(edge[i].cap > edge[i].flow && dep[v] == -1){
                dep[v] = dep[u] + 1;
                if(v == t) return true;
                Q[tail++] = v;
            }
        }
    }
    return false;
}
int dinic(int s,int t,int n){
    int maxflow = 0;
    while(bfs(s,t,n)){
        for(int i=0;i<n;i++) cur[i] = head[i];
        int u = s,tail = 0;
        while(cur[s] != -1){
            if(u == t){
                int tp = INF;
                for(int i=tail-1;i>=0;i--) tp = min(tp, edge[sta[i]].cap-edge[sta[i]].flow);
                maxflow+=tp;
                for(int i=tail-1;i>=0;i--){
                    edge[sta[i]].flow+=tp;
                    edge[sta[i]^1].flow-=tp;
                    if(edge[sta[i]].cap-edge[sta[i]].flow==0) tail = i;
                }
                u = edge[sta[tail]^1].to;
            }else if(cur[u] != -1 && edge[cur[u]].cap > edge[cur[u]].flow && dep[u] +1 ==dep[edge[cur[u]].to]){
                sta[tail++] = cur[u];
                u = edge[cur[u]].to;
            }else{
                while(u != s && cur[u] == -1) u = edge[sta[--tail]^1].to;
                cur[u] = edge[cur[u]].next;
            }
        }
    }
    return maxflow;
}

struct node{
    int v,c;
    node(int vv,int cc):v(vv),c(cc) {}
};
vector<node> E[MAXN];
int dis[MAXN];
bool vis[MAXN];
void SPFA(int start,int n,int (&dis)[MAXN],bool vis[MAXN],vector<node> E[MAXN]){
    vis[start]=true,dis[start]=0;
    queue<int> q;q.push(start);
    while(q.size()){
        int u = q.front();q.pop();
        vis[u]=false;
        for(int i=0;i<E[u].size();i++){
            int v = E[u][i].v,c =  E[u][i].c;
            if(dis[v]>dis[u]+c){
                dis[v]=dis[u]+c;
                if(!vis[v]){
                    vis[v] = true;
                    q.push(v);
                }
            }
        }
    }
}
int n,m,s,t;
bool init_2(){
    scanf("%d%d",&n,&m);
    for(int i=0;i<n;i++){
        dis[i] = INF;
        vis[i] = false;
        E[i].clear();
    }
    for(int i=0;i<m;i++){
        int a,b,c;scanf("%d%d%d",&a,&b,&c);
        if(a==b) continue;
        E[a-1].push_back(node(b-1,c));
    }
    scanf("%d%d",&s,&t);
    s--,t--;
    SPFA(s,n,dis,vis,E);
    if(dis[t]==INF) return false;
    init();
    for(int i=0;i<n;i++){
        for(int j=0;j<E[i].size();j++){
            int v = E[i][j].v;
            if(dis[i] + E[i][j].c == dis[v]) addedge(i,v,1);
        }
    }
    return true;
}

int main(){
    int _;scanf("%d",&_);
    while(_--){
        if(!init_2()) puts("0");
        else printf("%d\n",dinic(s,t,n));
    }
    return 0;
}


R - 0 or 1HDU - 4370 

题意:给你一个n*n矩阵C,然后n*n矩阵X只能是0或者1,问你矩阵这么填充数字,满足以下所有条件

1.X12+X13+...X1n=1
2.X1n+X2n+...Xn-1n=1
3.for each i (1<i<n), satisfies ∑Xki (1<=k<=n)=∑Xij (1<=j<=n).

并且 ∑Cij*Xij(1<=i,j<=n) 最小

算法:矩阵转换路径图条件(构图)+SPFA

思路:因为之前做了dancingLink,导致我往那边想,当我越陷越深,才发现我做的是一道最短路径题,我就想着往图那边想;但是趋于自己过于愚笨,最后还是百度借鉴他人思路;大佬博客:https://www.cnblogs.com/xiongtao/p/10318440.html

以下是我看完自己的想法;

第一:考虑X(i,i) ,条件1,2没涉及 ,条件3涉及,但是左右两边都有,相减就不涉及了,所以X(i,i)都设置为0,都满足条件1,2,3;并且使得∑Cij*Xij(1<=i,j<=n)更小了。这里其实间接表示,这张图,没有必要存在自身点连接的边;

第二:把矩阵X看成一个图的边邻接矩阵,1表示这个单向边存在,0表示这个单向边不存在;则矩阵C表示这个边的费用;那么条件1,代表的意思就是,点1出去的边有且仅有一条,并且只能是其他点——出度为1;同理条件2,代表的意思就是,点n进来的边有且仅有一条,并且只能是其他点——入度为1;条件3,则表示对于for each i (1<i<n),点i有多少边进来就有多少边出去——点i的出入度都相等——点i不可能作为联通路径的结束点或者起始点;所以有个起点一定是点1,结束点为n的路径————点1必须是一条路的起点,点n必须是一条路的终点;但对于点1入度的和点n出度没规定,所以存在两种情况:

第一情况:这张图存在一个1到n的路径,因为答案要求最小,所以这个路径必须费用最小且不成环;第二情况:存在一个1到1自己的路径环,并且n到n自己的路径环,两条环路(因为点1必须是一条路的起点,点n必须是一条路的终点),并且这两个环总费用要最低;

所以答案就是两种情况的最小值;

解决办法:这里将X12、X13、...X1n加进队列,跑一次点1为起点的SPFA,因为这些边都是互斥——所有可能性都进一次队列且图所有边都是正向边,所以跑出最短路径dis[n]就是情况1费用,且dis[1]为1自环路径的最短路径费用;同理跑一次点n为起点的SPFA,dis[n]为n自环路径的最短路径费用;答案就是,min(SPFA1_dis[n], SPFA1_dis[1]+SPFAN_dis[n])

查看代码
 #include <iostream>
#include <cstdio>
#include <cstring>
#include <string.h>
#include <queue>
#include <vector>
#include <stack>
#include <cmath>
#include <map>
#include <limits.h>
#include <float.h>

#define sc scanf
#define pf printf
#define REP(i,a,b) for(int i=(a);i<(b);i++)
#define CLR(x,m) memset(x,m,sizeof x);
#define LOCAL freopen("test.txt","r",stdin)
#define UCCU ios::sync_with_stdio(0);
#define XSD(i) cout << fixed << setprecision(i);
#define pii pair<int,int>
#define xx first
#define yy second

using namespace std;

typedef long long LL;
typedef unsigned long long ULL;
typedef double DB;
typedef long double LDB;

const double eps = 1e-8;
//const int inf = 1<<30;
const int INF = 0x3f3f3f3f;
const long long llinf = (long long)300100*1000000000;
const DB PI = acos(-1.0);
const LL mod = 1e9+7;

//-----------------------------------------------------------------------
int C[303][303],n;
int dis[303];
bool vis[303];
void SPFA(int start){
    queue<int> q;
    for(int i=1;i<=n;i++){
        if(i==start) dis[i] = INF,vis[i] = false;
        else dis[i] = C[start][i],vis[i] = true,q.push(i);
    }
    while(q.size()){
        int u = q.front();q.pop();
        vis[u] = false;
        for(int i=1;i<=n;i++){
            if(i==u) continue;
            if(dis[i]>dis[u]+C[u][i]){
                dis[i]=dis[u]+C[u][i];
                if(!vis[i]){
                    vis[i] = true;
                    q.push(i);
                }
            }
        }
    }
}

int main(){
    while(~scanf("%d",&n)){
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++) scanf("%d",&C[i][j]);
        SPFA(1);
        int ans = dis[n],tmp = dis[1];
        SPFA(n);
        ans = min(ans, tmp+dis[n]);
        printf("%d\n",ans);
    }
    return 0;
}


LayoutPOJ - 3169

题意:n个牛,然后每个牛有两种逻辑关系:

Lines 2..ML+1: Each line contains three space-separated positive integers: A, B, and D, with 1 <= A < B <= N. Cows A and B must be at most D (1 <= D <= 1,000,000) apart.

A牛和B牛最多相距D远  B <= A + D

Lines ML+2..ML+MD+1: Each line contains three space-separated positive integers: A, B, and D, with 1 <= A < B <= N. Cows A and B must be at least D (1 <= D <= 1,000,000) apart.

A牛和B牛最多至少D远 A <= B - D

算法:差分约束+SPFA

思路:这题与之前糖果题目—— CandiesPOJ - 3159 思路一模一样;但是我这里wrong了几次,只是因为题目中写了,牛会按照编号顺序那样排号,但是可以多个牛在同一位置,即顺序关系不变,但是一个坑可以多牛站;但是如果我在结果如果加上顺序判断的时候,就会wrong;如果删掉就会accept!!

查看代码
 #include <iostream>
#include <cstdio>
#include <cstring>
#include <string.h>
#include <queue>
#include <vector>
#include <stack>
#include <cmath>
#include <map>
#include <limits.h>
#include <float.h>

#define sc scanf
#define pf printf
#define REP(i,a,b) for(int i=(a);i<(b);i++)
#define CLR(x,m) memset(x,m,sizeof x);
#define LOCAL freopen("test.txt","r",stdin)
#define UCCU ios::sync_with_stdio(0);
#define XSD(i) cout << fixed << setprecision(i);
#define pii pair<int,int>
#define xx first
#define yy second

using namespace std;

typedef long long LL;
typedef unsigned long long ULL;
typedef double DB;
typedef long double LDB;

const double eps = 1e-8;
//const int inf = 1<<30;
const int INF = 0x3f3f3f3f;
const long long llinf = (long long)300100*1000000000;
const DB PI = acos(-1.0);
const LL mod = 1e9+7;

//-----------------------------------------------------------------------
const int MAXN = 1000 + 10;
//const int MAXM = 2000 + 10;
struct edge{
    int v,w;
    edge(int vv,int ww):v(vv),w(ww) {}
};
vector<edge> Edge[MAXN];
void addedge(int u,int v,int w){Edge[u].push_back(edge(v,w));}
int dis[MAXN], cnt[MAXN];
bool vis[MAXN];
bool SPFA(int n){
    queue<int> q;
    dis[1] = 0;vis[1] = true;cnt[1]=1;q.push(1);
    for(int i=2;i<=n;i++){
        dis[i] = INF,vis[i] = false,cnt[i]=0;
    }
    while(q.size()){
        int u = q.front();q.pop();
        vis[u] = false;
        for(int i=0;i<Edge[u].size();i++){
            int v = Edge[u][i].v, w = Edge[u][i].w;
            if(dis[v]>dis[u]+w){
                dis[v]=dis[u]+w;
                //if(dis[v]<0) return false;
                if(!vis[v]){
                    if(++cnt[v]>n) return false;
                    vis[v] = true;
                    q.push(v);
                }
            }
        }
    }
    //for(int i=2;i<=n;i++) if(dis[i]<dis[i-1]) return false;
    return true;
}

int main(){
    int n,m,k;scanf("%d%d%d",&n,&m,&k);
    while(m--){
        int a,b,c;scanf("%d%d%d",&a,&b,&c);
        addedge(a,b,c);
    }
    while(k--){
        int a,b,c;scanf("%d%d%d",&a,&b,&c);
        addedge(b,a,-c);
    }
    if(!SPFA(n)) puts("-1");
    else if(dis[n]==INF) puts("-2");
    else printf("%d\n",dis[n]);
    return 0;
}


最后一行。。谢谢观看

 

posted @ 2022-09-15 00:19  Bug_Clearlove  阅读(28)  评论(0编辑  收藏  举报