该题有两种输入
1、P A B X 。表示A到B的距离点明了为X:A-B==X,等价于A-B<=X&& A-B>=X (B-A<=-X)。于是得到两条边(A,B,X)和(B,A,-X)。
以前我很纠结A-B<=X是建成(A,B,X)呢,还是(B,A,X)呢,今天我实践了一下,发现都无关紧要,关键是接下来的所有边,你都得按照这个顺序来就是了!
2、V A B 。表示A到B的距离最少为1:即A-B>=1,等价于B-A<=-1,得到边(B,A,-1)。
最后再从原点向所有点引一条边权为0的边(S,i,0) i=1->n。
图建好了,用SPFA求解即可,如果不存在负环的话,则一定有解!
这题属于水题,不过带给了我一下收获:
1、A,B的距离恒为X的时候,可以将A-B==X 转化为A-B>=X&& A-B<=X
2、A-B<=X的时候不必纠结建A->B 还是B->A,只需要保证接下来的所有边都按某一个规则就是了
3、SPFA判断负环的条件是cut[X]>n,其中n为图中所有的节点数。
#include<iostream>
#include<string>
#include<queue>
using namespace std;
#define inf 0xfffffff
typedef struct node
{
int v;
int w;
struct node *next;
}node;
node *link[1005];
node edge[205000];
int num;
void add(int u,int v,int w)
{
edge[num].v=v;
edge[num].w=w;
edge[num].next=link[u];
link[u]=edge+num++;
}
int n,m;
int v[1005],dist[1005],cut[1005];
int spfa()
{
queue<int>Q;
for(int i=0;i<=n;i++)
{
v[i]=0;
dist[i]=inf;
cut[i]=0;
}
v[0]=1;
dist[0]=0;
Q.push(0);
cut[0]=1;
while(!Q.empty())
{
int x=Q.front();
Q.pop();
v[x]=0;
for(node *p=link[x];p;p=p->next)
{
if(dist[p->v]>dist[x]+p->w)
{
dist[p->v]=dist[x]+p->w;
if(!v[p->v])
{
v[p->v]=1;
cut[p->v]++;
if(cut[p->v]>n+1) //还有原点算一个点
return 0;
Q.push(p->v);
}
}
}
}
return 1;
}
int main()
{
int i,a,b,w;
char c;
freopen("D:\\in.txt","r",stdin);
while(scanf("%d%d",&n,&m)!=EOF)
{
scanf("%*c");
memset(link,0,sizeof(link));
num=0;
for(i=0;i<m;i++)
{
scanf("%c",&c);
if(c=='P')
{
scanf("%d%d%d",&a,&b,&w);
add(a,b,w);
add(b,a,-w);
}
else
{
scanf("%d%d",&a,&b);
add(b,a,-1);
}
scanf("%*c");
}
for(i=1;i<=n;i++)
{
add(0,i,0);
}
if(spfa())
{
printf("Reliable\n");
}
else
{
printf("Unreliable\n");
}
}
return 0;
}