hdu-1317 XYZZY---Floyd判连通+bellman最短路

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=1317

题目大意:

题意:有n个房间(n<=100),每个房间有一个点权(第1号房间和第n号房间权值均为0),到达该房间时会自动获得该点权(可能为负权)。给出一些无向边。有一个人,初始有能量值100,初始位置是第1号房间,要走到第n号房间,且路途中不得使身上能量值小于或等于0。能到达第n个房间就算赢,问能否赢。

解题思路:

这里最坑的是第一号房间可能和最后一个房间连通不了。所以首先得判断连通性,再Bellman求最短路。

如果floyd判断房间1和房间n不连通,直接输出失败

如果在第n次还在松弛并且松弛的点可以到达终点n,说明存在正环且该正环能到达n,此时一定是成功的。

如果到达n的时候能量值为正数则成功,为0或者负数则失败

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int maxn = 10000 + 10;
 5 const int INF = 0x3f3f3f3f;
 6 struct edge
 7 {
 8     int u, v, w;
 9     edge(){}
10     edge(int u, int v, int w):u(u), v(v), w(w){}
11 };
12 edge e[maxn];
13 bool Map[105][105];
14 int num[105], n, d[maxn], tot;
15 void addedge(int u, int v, int w)
16 {
17     e[tot++] = edge(u, v, w);
18 }
19 void floyd()//判断连通性
20 {
21     for(int k = 1; k <=n; k++)
22     {
23         for(int i = 1; i <= n; i++)
24         {
25             for(int j = 1; j <= n; j++)
26             {
27                 Map[i][j] |= (Map[i][k]&Map[k][j]);
28             }
29         }
30     }
31 }
32 bool Bellman(int u)
33 {
34     memset(d, -INF, sizeof(d));
35     d[u] = 100;
36     for(int i = 0; i < n; i++)
37     {
38         for(int j = 0; j < tot; j++)
39         {
40             int u = e[j].u, v = e[j].v, w = e[j].w;
41             if(d[u] + w > d[v] && d[u] > 0)//d[u]>0说明只有能量为正的点才可以对其相邻的边进行松弛
42             {
43                 d[v] = d[u] + w;
44                 if(i == n - 1 && Map[v][n])
45                 //i==n-1说明第n次迭代还在松弛,说明存在正环
46                 //Map[v][n]=1说明松弛的点可以到达终点(这里改成Map[u][n]也是一样的,因为这两个的值是一样的,因为存在边<u, v>)
47                 //满足上面两个条件说明存在一个正环,且该环可以到达终点
48                 //可以一直在正环中运动使得能量值无穷大,最后就一定能到终点
49                     return 1;
50             }
51         }
52     }
53     return d[n] > 0;
54 }
55 int main()
56 {
57     while(cin >> n && n != -1)
58     {
59         int t, x;
60         tot = 0;
61         memset(Map, 0, sizeof(Map));
62         for(int i = 1; i <= n; i++)
63         {
64             cin >> num[i];
65             cin >> t;
66             while(t--)
67             {
68                 cin >> x;
69                 Map[i][x] = 1;
70             }
71         }
72         for(int u = 1; u <= n; u++)
73         {
74             for(int v = 1; v <= n; v++)
75             {
76                 if(Map[u][v])addedge(u, v, num[v]);
77             }
78         }
79         floyd();
80         if(!Map[1][n])cout<<"hopeless"<<endl;//1-n直接不连通
81         else if(Bellman(1))cout<<"winnable"<<endl;
82         else cout<<"hopeless"<<endl;
83     }
84     return 0;
85 }

 

posted @ 2018-04-22 22:01  _努力努力再努力x  阅读(189)  评论(0编辑  收藏  举报