[HDOJ1317]XYZZY(SPFA, floyd)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1317

题意:给一张有向的点权图,一个人在起点有初始值100,这个人从一个点到另一个点时要加上对应目标点的权值。问有没有一条路径使得这个人的当前值都是正数的前提下,到达终点。

由于问能不能,考虑一个情况就是有正数环的情况,假如这个环可以到达终点,那么无论如何都可以到达终点。这个可达的状态可以通过floyd来求传递闭包得出。因为相当于是求最长路,那么负环就不必要考虑了。

所以做法就是先floyd求出传递闭包,在基础上做spfa,更新两个点之间的时候要考虑是否可达。

 1 #include <cstdio>
 2 #include <queue>
 3 #include <vector>
 4 #include <cstring>
 5 #include <iostream>
 6 #include <algorithm>
 7 using namespace std;
 8 typedef pair<int, int> pii;
 9 
10 const int maxn = 110;
11 const int maxm = 10100;
12 const int inf = 0x7f7f7f;
13 const int nl = 100;
14 vector<pii> G[maxn];
15 bool dp[maxn][maxn];
16 int vcnt[maxn];
17 int d[maxn];
18 queue<int> q;
19 int n, m;
20 
21 void floyd() {
22     for(int k = 1; k <= n; k++) {
23         for(int i = 1; i <= n; i++) {
24             for(int j = 1; j <= n; j++) {
25                 if(dp[i][k] && dp[k][j]) {
26                     dp[i][j] = 1;
27                 }
28             }
29         }
30     }
31 }
32 
33 bool spfa(int s) {
34     memset(vcnt, 0, sizeof(vcnt));
35     for(int i = 1; i <= n; i++) d[i] = -inf;
36     while(!q.empty()) q.pop();
37     q.push(s); d[s] = 100;
38     while(!q.empty()) {
39         int u = q.front(); q.pop();
40         if(vcnt[u] > nl) return dp[u][n];
41         for(int i = 0; i < G[u].size(); i++) {
42             int v = G[u][i].first, w = G[u][i].second;
43             if(dp[u][v] && d[v] < d[u] + w && d[u] + w > 0) {
44                 d[v] = d[u] + w;
45                 vcnt[v]++;
46                 q.push(v);
47             }
48         }
49     }
50     return d[n] > 0;
51 }
52 
53 int main() {
54     // freopen("in", "r", stdin);
55     int v, w, m;
56     while(~scanf("%d",&n) && ~n) {
57         memset(dp, 0, sizeof(dp));
58         for(int i = 1; i <= n; i++) {
59             G[i].clear();
60         }
61         for(int u = 1; u <= n; u++) {
62             scanf("%d %d", &w, &m);
63             while(m--) {
64                 scanf("%d", &v);
65                 dp[u][v] = 1;
66                 G[u].push_back(pii(v, w));
67             }
68         }
69         floyd();
70         if(dp[1][n]) {
71             if(spfa(1)) puts("winnable");
72             else puts("hopeless");
73         }
74         else puts("hopeless");
75         // for(int i = 1; i <= n; i++) printf("%d ", d[i]);
76         // printf("
");
77     }
78     return 0;
79 }
原文地址:https://www.cnblogs.com/kirai/p/5871967.html