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;

}

你可能感兴趣的:(差分约束)