同上..用SPFA来解决...用SPFA的第一个问题是如何跳出while..因为这题明显的可能有负环..SPFA如果普通的...有负环..则会将环上的点不断入队列..就会死循环!!为了能跳出死循环或者说能判断出有负环..就用个数组来记录每个点入队的次数...如果入队的次数超过点的总数N了..则可以判断出是出现负环了..这个思想是从Bellman-Ford那来的..回想Bellman-Ford..外围是用来循环次数..是循环了N次..第二层则循环所有的边..可以发现一个点最多就更新循环次数N了...

   再一个要注意的是用SPFA就必须先要确定源点然后入队...但这里如果任意确定源点会出错...因为这题的图不一定时连通的~~有可能有多个独立的图..有多个源点..所以要么就在开始时将所有点入队...d [ ] 统一赋值为0...要么加一个超级点指向所有点权值为0....其实本质是一样的...


Program:

#include<iostream>
#include<queue>
using namespace std;
struct pp
{
int x,y,k,next;
}line[300001];
int n,m,i,x,y,k,link[1010];
char c;
queue<int> myqueue;
bool SPFA()
{
int i,h,k,d[1010],sum[1010];
bool used[1010];
for (i=1;i<=n;i++)
{
m++;
line[m].x=0; line[m].y=i; line[m].k=0;
line[m].next=link[0]; link[0]=m;
}
while (!myqueue.empty()) myqueue.pop();
memset(d,0x7F,sizeof(d));
memset(sum,0,sizeof(sum));
memset(used,false,sizeof(used));
d[0]=0; myqueue.push(0);
while (!myqueue.empty())
{
h=myqueue.front();
myqueue.pop();
used[h]=false;
k=link[h];
while (k)
{
if (d[line[k].y]>d[h]+line[k].k)
{
d[line[k].y]=d[h]+line[k].k;
if (!used[line[k].y])
{
myqueue.push(line[k].y);
sum[line[k].y]++;
if (sum[line[k].y]>n) return false;
used[line[k].y]=true;
}
}
k=line[k].next;
}
}
return true;
}
int main()
{
while (~scanf("%d%d",&n,&m))
{
i=m;
m=0;
memset(link,0,sizeof(link));
while (i--)
{
c=getchar();
while (c!='V' && c!='P' ) c=getchar(); ;
if (c=='P')
{
scanf("%d%d%d",&y,&x,&k);
m++;
line[m].x=x; line[m].y=y; line[m].k=k;
line[m].next=link[x]; link[x]=m;
m++;
line[m].x=y; line[m].y=x; line[m].k=-k;
line[m].next=link[y]; link[y]=m;
}else
{
scanf("%d%d",&x,&y);
m++;
line[m].x=x; line[m].y=y; line[m].k=-1;
line[m].next=link[x]; link[x]=m;
}
}
if (SPFA()) printf("Reliable\n");
else printf("Unreliable\n");
}
return 0;
}