POJ 2983(差分约束系统)

POJ 2983

(1)题意:

有两种信息,

P A B X表示A在B点的北边的准确距离为X

V A B表示A在B的北边,但是具体的距离不确定,但是距离一定大于1.

询问是否存在一种情况使N个据点满足之前的条件。

(2)思路:

建立一个图,源点为n+1,建图求最长路,如果图中存在正环,结果不可信,

否则可信。

建立关系如下:

P B-A>=x, A-B>=-x

V A-B>=1

然后判断是否存在正环即可。

(3)代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 1024;
const int INF = 1e9+10;
const int maxm = 1e5+10;
int head[maxn],vis[maxn],dis[maxn],tim[maxn],tot,n,m,st[maxm];
struct Node{
	int v,nxt,w;
}cur[maxm<<2];
void Init(){
	memset(head,-1,sizeof(head));
	tot = 0;
}
void Add(int x,int y,int z){
	cur[tot] = Node{y,head[x],z};
	head[x] = tot++;
} 
bool spfa(int pos){
	for(int i=0;i<=pos;i++){
		dis[i] = -INF;tim[i] = 0;vis[i] = 0;
	}
	int top = 0;
	st[top++] = pos;dis[pos] = 0;tim[pos]++;
	while(top!=0){
		int x = st[--top];vis[x] = 0;
		for(int i=head[x];i!=-1;i=cur[i].nxt){
			int y = cur[i].v;
			if(dis[y]<dis[x]+cur[i].w){
				dis[y] = dis[x]+cur[i].w;
				if(vis[y]==0){
					vis[y] = 1;
					st[top++] = y;
					if(++tim[y]>n+2) return false;
				}
			}
		}
	}
	return true;
}
int main(void){
	while(~scanf("%d%d",&n,&m)){
		Init();
		for(int i=0;i<m;i++){
			char ss[5];
			scanf("%s",ss);
			if(ss[0]=='P'){
				int x,y,z;scanf("%d%d%d",&x,&y,&z);
				Add(x,y,-z);
				Add(y,x,z);
			}
			else{
				int x,y;scanf("%d%d",&x,&y);
				Add(y,x,1);
			}
		}
		int pos = n+1;
		for(int i=0;i<=n;i++) Add(pos,i,0);
		if(spfa(pos)==true) printf("Reliable\n");
		else printf("Unreliable\n");
	}
	
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41829060/article/details/91628176