POJ 2983 Is the Information Reliable? [ 差分约束系统 spfa]

思路:

差分约束还是很神奇。


我的理解,本质是在对N个点排序,这么多点之间有距离关系,因为存在V这种模糊距离关系,所以距离关系有约束。

顾用差分约束系统来解决。

主要差分方程:

1.i-j>=w && i-j<=w (j-i>=-w);

2.i-j>=1;


spfa松弛方程

if(d[v]<d[u]+w)

d[v]=d[u]+w;

即d[i]始终保存节点i的取值范围的左边界。


然后则是检查负环,如果某个节点入队列次数>n,则有负环。(由bellman-ford得知边的松弛次数最大只需N-1).


#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
#define Abs(a) ((a)>0?(a):(-(a)))
#define llong long long int
using namespace std;
const int N=1005,M=100005;
const int inf=(1<<30);
int n,m;
struct Edge
{
	int v,w,next;
}edge[3*M];
int edgehead[N];
int _n;
int que[N*N];
int d[N];
bool vis[N];
int times[N];
void addedge(int u ,int v,int w)
{	
	edge[_n].v=v;
	edge[_n].w=w;
	edge[_n].next=edgehead[u];
	edgehead[u]=_n++;
}
bool spfa(int s)
{
	bool ans=true;
	memset(vis,0,sizeof(vis));
	memset(times,0,sizeof(times));
	int head=1,tail=1;
	que[tail++]=s;
	times[s]=1;
	vis[s]=true;
	while(head<tail&&ans)
	{
		int now=que[head++];
		vis[now]=false;
		for(int i=edgehead[now];i;i=edge[i].next)
		{
			int v=edge[i].v;
			int w=edge[i].w;
			if(d[v]<d[now]+w)
			{
				d[v]=d[now]+w;
				if(!vis[v])
				{
					if(times[v]>n)
					{
						ans=false;
						break;
					}
					vis[v]=true;
					que[tail++]=v;
					times[v]++;
				}
			}
		}
	}
	return ans;
}
void solve()
{
	int s=n+1;
	for(int i=1;i<=n;i++)
	  addedge(s,i,1);
	if(spfa(s))
	  printf("Reliable\n");
	else
	  printf("Unreliable\n");
}
int main()
{
	while(scanf("%d%d",&n,&m)!=EOF)
	{
		_n=1;
		memset(d,0,sizeof(d));
		memset(edge,0,sizeof(edge));
		memset(edgehead,0,sizeof(edgehead));
		char cha;
		int u,v;
		for(int i=1;i<=m;i++)
		{
			scanf(" %c",&cha);
			scanf("%d%d",&u,&v);
			if(cha=='P')
			{
				int w;
				scanf("%d",&w);
				addedge(u,v,w);
				addedge(v,u,-w);
			}
			else
			{
				addedge(u,v,1);
			}
		}
		solve();
	}
	return 0;
}


你可能感兴趣的:(POJ 2983 Is the Information Reliable? [ 差分约束系统 spfa])