pku 2983 差分约束系统判断

该题有两种输入

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;
}
原文地址:https://www.cnblogs.com/ka200812/p/2125624.html