题意:给出一些不等式,求是否存在可行解。
分析:差分约束系统,对于bellman和spfa来说,解差分的不同在于,对于不连通图bellman能直接处理,而spfa不能,需要加入超级源(一个到所有点都有一条长度为0的边的点),并把超级源作为起点,才能保证在扩展过程中到达每个点。否则差分约束系统的部分内容就不会被检测到。当然也不是所有题遇到这种不连通的情况都可以使用超级源。因为这种超级源相当于把不同的连通分支在数轴上的起点都平移到了原点。如题目有特殊要求,则可以对不同的连通分支分别做单独处理。
Description
The galaxy war between the Empire Draco and the Commonwealth of Zibu broke out 3 years ago. Draco established a line of defense called Grot. Grot is a straight line with N defense stations. Because of the cooperation of the stations, Zibu’s Marine Glory cannot march any further but stay outside the line.
A mystery Information Group X benefits form selling information to both sides of the war. Today you the administrator of Zibu’s Intelligence Department got a piece of information about Grot’s defense stations’ arrangement from Information Group X. Your task is to determine whether the information is reliable.
The information consists of M tips. Each tip is either precise or vague.
Precise tip is in the form of P A B X
, means defense station A is X light-years north of defense station B.
Vague tip is in the form of V A B
, means defense station A is in the north of defense station B, at least 1 light-year, but the precise distance is unknown.
Input
There are several test cases in the input. Each test case starts with two integers N (0 < N ≤ 1000) and M (1 ≤ M ≤ 100000).The next M line each describe a tip, either in precise form or vague form.
Output
Output one line for each test case in the input. Output “Reliable” if It is possible to arrange N defense stations satisfying all the M tips, otherwise output “Unreliable”.
Sample Input
3 4 P 1 2 1 P 2 3 1 V 1 3 P 1 3 1 5 5 V 1 2 V 2 3 V 3 4 V 4 5 V 3 5
Sample Output
Unreliable Reliable
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #define INF 0x3f3f3f3f #define maxn 200000 int n,m,cnt; struct node { int u,v,w; } edge[maxn]; int dis[maxn]; void add(int u,int v,int w) { edge[cnt].u=u; edge[cnt].v=v; edge[cnt].w=w; cnt++; } int BM() { memset(dis,0,sizeof(dis));//初始化原点到各点的距离 int flag; //用于优化,节省时间 for(int i=0; i<n; i++) { flag=1; for(int j=0; j<cnt; j++) { if(dis[edge[j].v]>dis[edge[j].u]+edge[j].w) { dis[edge[j].v]=dis[edge[j].u]+edge[j].w; flag=0; } } if(flag) //若dis没有任何改变,则以后也不会改变,可以直接退出循环 break; } ///循环n次后若flag == 0 说明有负权回路,或者权值矛盾 return flag; } int main() { char g; int a,c,b; while(~scanf("%d %d",&n,&m)) { cnt=0; while(m--) { getchar(); scanf("%c",&g); if(g=='P') { scanf("%d %d %d",&a,&b,&c); add(a,b,-c); //建立双向边 add(b,a,c); } else { scanf("%d %d",&a,&b); add(a,b,-1); } } if (BM()) printf("Reliable\n");// 不存在负权环 else printf("Unreliable\n");//存在负权环 } return 0; }