HDU 1373 XYZZY (spfa的特殊用法)

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

题目大意:有n个房间,编号1~n,房间之间有单向门连接。某人初始位于1号房间,且具有100点能量。此人要去n号房间,中途每经到一个房间Ri,其能量值会加上一个值ai,当其能量值小于等于0的时候会死掉。问此人能否到达n号房间。n<100, -100 <= ai <= 100。

分析:将房间看做结点,单向门看成单向边,形成一张有向图,问题转换为搜索一条从1号点能到达n号点的路径。

  使用SPFA算法搜索最长路。如果图中不存在环,则找一条最长路即可。

  否则,存在负环不影响结果。

  如果存在正环,在顶点第n次进队列的时候,距离标记成无穷大,之后不在进队。这样,只要存在合理的路径,就一定能到达n点,不能到达说明无解。

参考代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <vector>
 4 using namespace std;
 5 #define N 110
 6 #define inf 1000000000
 7 
 8 vector<int>ve[N];
 9 
10 int w[N];
11 int Q[N*N];
12 bool inq[N];
13 int dis[N], cnt[N];
14 int id;
15 bool spfa(int n)
16 {
17     for(int i = 1; i <= n; i++)
18     {
19         dis[i] = -inf, inq[i] = 0, cnt[i] = 0;
20     }
21     dis[1] = 100;
22     int top = 0;
23     Q[top++] = 1;
24     inq[1] = cnt[1] = 1;
25     for(int i = 0; i < top; i++)
26     {
27         int u = Q[i];
28         inq[u] = 0;
29         if(dis[u]+w[u] <= 0) continue;
30         int m = ve[u].size();
31         for(int j = 0; j < m; j++)
32         {
33             int v = ve[u][j];
34             if(dis[v] < dis[u] + w[u])
35             {
36                 dis[v] = dis[u] + w[u];
37                 if(v == n) return true;
38                 if(!inq[v])
39                 {
40                     cnt[v]++;
41                     if(cnt[v] > n) continue;
42                     if (cnt[v] == n) 
43                         dis[v] = inf;
44                     Q[top++] = v;
45                     inq[v] = 1; 
46                 }
47             }
48         }
49     }
50     return false;
51 }
52 int main()
53 {
54     int n;
55     while(~scanf("%d", &n), ~n)
56     {
57         for(int i = 1; i <= n; i++) ve[i].clear();
58         for(int i = 1; i <= n; i++)
59         {
60             int m, t;
61             scanf("%d", &w[i]);
62             scanf("%d", &m);
63             for(int j = 0; j < m; j++)
64             {
65                 scanf("%d", &t);
66                 ve[i].push_back(t);
67             }
68         }
69         bool res = spfa(n);
70         if(res) puts("winnable");
71         else puts("hopeless");
72     }
73     return 0;
74 }

 

posted @ 2015-08-07 15:20  beisong  阅读(376)  评论(0编辑  收藏  举报