UVA 10557 XYZZY

13500 ワード

UVA_10557
このテーマは実際に起点から終点までの最長の道を求めている.
ただし、通過する各ポイントの重み値は負にならないため、距離配列d[]を初期化する際に0を初期化する.その後,キュー最適化のBellman−Fordアルゴリズムを用いて最長の道を求めたが,まだいくつかの詳細に注意しなければならない.
もちろん,このアルゴリズムを用いた場合にd[n]>0を選択することで計算量を減らすことができるが,ある位置に正の輪が存在し,この正の輪が終点に到達できないとプログラムが走り続ける例も見つかる.しかし、同じように、私たちも輪を見て踊ることはできません.結局、いくつかの正輪がゴールに着くことができるからです.これは私たちにどの正輪がゴールに着くことができるかを判断することを要求します.
そこで、一番長い道を探す前に前処理をして、ゴールに着くことができるすべての点を見つけることができます.1つの良い方法は、ゴールから逆方向に深く検索し、検索した点を順番にマークすればいいです.最後の起点がマークされていなければ、hopelessを直接出力すればいいです.
後でキュー最適化のBellman-Fordアルゴリズムを使用する場合,判定条件に終点に到達するかどうかの判定を1つ追加すればよいが,この点が終点に到達すれば最長ルートを求める操作を行う.
#include<stdio.h>
#include
<string.h>
int G[110][110],w[110],d[110],n;
int q[110],inq[110],inedq[110];
int vis[110],reach[110];
void dfs(int v)
{
int u;
for(u=1;u<=n;u++)
if(G[u][v]&&!vis[u])
{
vis[u]
=1;
reach[u]
=1;
dfs(u);
}
}
int main()
{
int i,j,k,u,v,num,front,rear,flag;
while(1)
{
scanf(
"%d",&n);
if(n==-1)
break;
memset(G,
0,sizeof(G));
for(u=1;u<=n;u++)
{
scanf(
"%d",&w[u]);
scanf(
"%d",&num);
for(i=0;i<num;i++)
{
scanf(
"%d",&v);
G[u][v]
=1;
}
}
memset(vis,
0,sizeof(vis));
memset(reach,
0,sizeof(reach));
reach[n]
=1;
dfs(n);
if(!reach[1])
{
printf(
"hopeless
");
continue;
}
memset(inq,
0,sizeof(inq));
memset(inedq,
0,sizeof(inedq));
memset(d,
0,sizeof(d));
front
=rear=0;
d[
1]=100;
q[rear
++]=1;
inq[
1]=1;
inedq[
1]++;
flag
=0;
while(front!=rear)
{
u
=q[front++];
if(front>n)
front
=0;
inq[u]
=0;
for(v=1;v<=n;v++)
if(G[u][v]&&reach[v]&&d[u]+w[v]>d[v])
{
d[v]
=d[u]+w[v];
if(!inq[v])
{
q[rear
++]=v;
if(rear>n)
rear
=0;
inq[v]
=1;
if(inedq[v]++>n)
{
flag
=1;
break;
}
}
}
if(d[n]>0||flag)
break;
}
if(d[n]>0||flag)
printf(
"winnable
");
else
printf(
"hopeless
");
}
return 0;
}