Holy Grail【spfa求最短路】

题目链接:https://www.jisuanke.com/contest/3004?view=challenges

题目大意:

1.一个无向图,给出六个顶点,添六条边,但是添边是有限制的。每次添边的权值要最小。

2.不能构成negative-weighted loop,negative-weighted loop指的是循环加权和为负,即从一个顶点出发在回到这个顶点的经过路径的权值和必须是 >= 0的。所以让你在u,v顶点天一条边,可以计算v - > u的最短路,然后加个负号取反。然后再加边执行下一次询问。需要进行6次SPFA。

3.dijsktra不能处理负边权,这里的边是带负的,所以用spfa,并且注意边权范围是 -1e9~1e9,所以两点之间最短路可能会超int范围,所以dis数组要开long long型。


代码如下:

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<queue>
 4 #define mem(a, b) memset(a, b, sizeof(a))
 5 #define LL long long
 6 const int inf = 0x3f3f3f3f;
 7 using namespace std;
 8 
 9 int n, m;
10 int head[310], cnt, vis[310];
11 LL dis[310];
12 
13 struct Edge
14 {
15     int to, next;
16     LL w;
17 }edge[510];
18 
19 void add(int a, int b, LL c)
20 {
21     edge[++ cnt].to = b;
22     edge[cnt].w = c;
23     edge[cnt].next = head[a];
24     head[a] = cnt;
25 }
26 
27 void spfa(int st, int ed)
28 {
29     mem(vis, 0), mem(dis, inf);
30     queue<int> Q;
31     Q.push(st);
32     dis[st] = 0;
33     vis[st] = 1;
34     while(!Q.empty())
35     {
36         int a = Q.front();
37         Q.pop();
38         vis[a] = 0;
39         for(int i = head[a]; i != -1; i = edge[i].next)
40         {
41             int to = edge[i].to;
42             if(dis[to] > dis[a] + edge[i].w)
43             {
44                 dis[to] = dis[a] + edge[i].w;
45                 if(!vis[to])
46                 {
47                     vis[to] = 1;
48                     Q.push(to);
49                 }
50             }
51         }
52     }
53 }
54 
55 int main()
56 {
57     int T;
58     scanf("%d", &T);
59     while(T --)
60     {
61         scanf("%d%d", &n, &m);
62         cnt = 0, mem(head, -1);
63         for(int i = 1; i <= m; i ++)
64         {
65             int a, b;
66             LL c;
67             scanf("%d%d%lld", &a, &b, &c);
68             add(a, b, c);
69         }
70         for(int i = 1; i <= 6; i ++)
71         {
72             int st, ed;
73             scanf("%d%d", &st, &ed);
74             spfa(ed, st);
75             printf("%lld\n", -dis[st]);
76             add(st, ed, -dis[st]);
77         }
78     }
79     return 0;
80 }
View Code

 

posted @ 2019-09-02 19:21  缘未到  阅读(187)  评论(0编辑  收藏  举报