http://acm.hdu.edu.cn/showproblem.php?pid=1317
最短路变型
注意环的问题 出现正环可以无限积累能量
用SPEA求最长路 可以找出正环
没有环的话就正常求最长路 有正环的话 就要模拟绕环积累能量 这样就可以跳过环
#include "stdio.h"
#include "string.h"
#include "vector"
#include "queue"
using namespace std;
const int maxn = 105;
const int inf = 1<<30;
int n;
int w[maxn],dis[maxn];
bool vis[maxn];
vector<int>map[maxn];
bool SPEA( int s )
{
queue<int>que;
int outque[maxn];
for( int i = 1; i <= n; i ++ )
dis[i] = -inf;
memset( vis,0,sizeof(vis) );
memset( outque,0,sizeof(outque) );
que.push(s);
vis[s] = true;
dis[s] = 100;//初始能量
while( !que.empty() )
{
int u = que.front(); que.pop();
vis[u] = false;
outque[u] ++;
if( outque[u] > n + 1 )//在等于n+1时已经模拟绕环无数次 之后跳过这个环
{
continue;
}
if( outque[u] == n + 1 ) //找到一个环 把dis[u]赋值为inf
dis[u] = inf;
for( int i = 0; i < map[u].size(); i ++ )
{
int v = map[u][i];
if( dis[v] < dis[u] + w[v] && dis[u] + w[v] > 0 )//能量不能小于等于0
{
dis[v] = dis[u] + w[v];
if( v == n )
return true;
if( !vis[v] )
{
vis[v] = true;
que.push( v );
}
}
}
}
return false;
}
int main()
{
//freopen( "data.txt","r",stdin );
int m,temp;
while( scanf("%d",&n) != EOF , n != -1 )
{
for( int i = 1; i <= n; i ++ )
{
map[i].clear();
scanf("%d%d",&w[i],&m);
for( int j = 1; j <= m; j ++)
{
scanf("%d",&temp);
map[i].push_back(temp);
}
}
if( SPEA(1) )
puts("winnable");
else
puts("hopeless");
}
return 0;
}