这题是我第一次用bellman-ford来做题,是我第一次用floyd来处理图的连通性,也是我第一次处理负权的情况,还是我第一次处理环;这一题首先用floyd来判断图的连通性,主要用来看起点到终点是否有路,还有是用来判断正环是否与终点连通;用bellman-ford来求出“最大的边”;在环的判断中关键的一句是
if(dis[y]<dis[x]+pointV[y]&&dis[x]+pointV[y]>0){if(g[y][n])return true; } dis[y]<dis[x]+pointV[y]在前面bellman-ford已经判断dis[y]=max(dis[y],dis[x]+pointV[y]);而现在dis[y]<dis[x]+pointV[y]说明有环形成;下面就直接上代码了,(因为没有初始化,wa了三四次,又因为数组开的不恰当,re了几次!不要再坑了!)
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int INF=0x3f3f3f3f;
const int maxn=105;
const int maxnl=10005;
int v[maxnl],u[maxnl],pointV[maxn];
int dis[maxn];
bool g[maxn][maxn];
int n;
void floyd(int n)
{
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
g[i][j]=g[i][j]||(g[i][k]&&g[k][j]);
}
bool bellmanFord(int from ,int to ,int n,int m)
{
for(int i=0;i<=n;i++)dis[i]=-INF;
dis[from]=100;
for(int k=0;k<n;k++){
for(int i=1;i<=m;i++){
int x=u[i],y=v[i];
if(dis[x]>-INF&&dis[x]+pointV[y]>0)
dis[y]=max(dis[y],dis[x]+pointV[y]);
}
}
for(int i=1;i<=m;i++){
int x=u[i],y=v[i];
if(dis[y]<dis[x]+pointV[y]&&dis[x]+pointV[y]>0){
if(g[y][n])return true;
}
}
return dis[to]>0;
}
int main()
{
//freopen("int.txt","r",stdin);
while(~scanf("%d",&n)&&n!=-1){
memset(g,false,sizeof(g));
memset(pointV,0,sizeof(pointV));
memset(u,0,sizeof(u));
memset(v,0,sizeof(v));
int cnt=1;
for(int i=1;i<=n;i++){
int val,m,to;
scanf("%d%d",&val,&m);
pointV[i]=val;
while(m--){
scanf("%d",&to);
u[cnt]=i;
v[cnt++]=to;
g[i][to]=true;
}
}
floyd(n);
if(!g[1][n])
{
printf("hopeless\n");
continue;
}
if(bellmanFord(1,n,n,cnt)){
printf("winnable\n");
}
else printf("hopeless\n");
}
return 0;
}