该题有两种输入
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; }