题目:
链接:点击打开链接
题意:
出发点1能量值为100,到达一个新的房间会得到一个+或-能量值,能否到终点。
思路:
用bellman_ford判断是否有环,如果存在环且能量值是大于0的,那么winnnable。如果起点1孤立,必然hopeless。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define INF 100000000
struct node
{
int from,to;
} edge[10010];
int n;
int first[110],next[10010],dis[110],power[110];
int map[110][110];
void add(node edge,int x)
{
next[x] = first[edge.from];
first[edge.from] = x;
}
void floyd()
{
for(int k=1; k<=n; k++)
{
for(int i=1; i<=n; i++)
{
for(int j=1; j<=n; j++)
{
if(!map[i][j])
map[i][j] = map[i][j] || (map[i][k] && map[k][j]);//有向图的传递闭包
}
}
}
}
int bellman_ford(int m)
{
for(int i=1; i<=n; i++)
dis[i] = -INF;
dis[1] = 100;//起点处能量值为100
for(int k=0; k<n-1; k++)
{
for(int i=0; i<m; i++)
{
int x = edge[i].from;
int y = edge[i].to;
if(dis[x] + power[y] > 0 && dis[y] < dis[x] + power[y])
dis[y] = dis[x] + power[y];
}
}
for(int i=0; i<m; i++)
{
int x = edge[i].from;
int y = edge[i].to;
if(dis[x] + power[y] > 0 && dis[y] < dis[x] + power[y] && map[y][n])
{
return 1;
}
}
return dis[n] > 0;
}
void init()
{
memset(edge,0,sizeof(edge));
memset(power,0,sizeof(power));
memset(map,0,sizeof(map));
memset(first,-1,sizeof(first));
memset(next,-1,sizeof(next));
}
int main()
{
freopen("input.txt","r",stdin);
int m,ct;
while(scanf("%d",&n) != EOF && n != -1)
{
init();
ct = 0;
for(int i=1; i<=n; i++)
{
scanf("%d%d",&power[i],&m);
for(int j=1; j<=m; j++)
{
int x;
scanf("%d",&x);
edge[ct].from = i;
edge[ct].to = x;
map[i][x] = 1;
add(edge[ct],ct);
ct++;
}
}
floyd();
if(!map[1][n])
{
printf("hopeless\n");
continue;
}
printf("%s\n",bellman_ford(ct) == 1 ? "winnable" : "hopeless");
}
return 0;
}
---------------------------------------------------------
战斗,从不退缩;奋斗,永不停歇~~~~~~~~~~~