POJ--2983[Is the Information Reliable?] 差分约束

47 篇文章 1 订阅
45 篇文章 0 订阅

 这题是判断图中是否存在环(用最短路或最长路), 开始用spfa, 狂WA,想不通,看了讨论说要添加一个超源点,添加了就AC了。

 

总结:

用spfa算法判断图中是否存在环,要保证从源点开始,能到达各个顶点,这样才能保证差分约束里的各个不等式成立。因为要是源点到达不了某个顶点的话(即图是不连通的),那么从该顶点就无法入队,导致从该顶点出发的所有不等式,都没有得到检查。


---------------------------------------------------------------------------------------------------
/*差分约束系统第一个题目所谓 P A B X 可以转换为xa-xb<=1 xb-xa<=-1  注意要加两条边,因为是相等,所以要两个不等式把它卡死V A B 转化为 xb-xa<=-1Bellman_Ford弄一下就行了据说spfa也行.判断一个点入队列的次数.如果大于n的话,就说明有权值和为负的回路*/
---------------------------------------------------------------------------------------------------

 

 

CODE:

/*差分约束(判断是否存在环)*/
/*AC代码:469ms*/
#include <iostream>
#define MAXN 1005
#define INF 0x7fffffff
using namespace std;
struct edge
{
	int v,w,next; 
}E[20005];
int head[MAXN],ecnt;
int Stack[MAXN],cnt[MAXN],dis[MAXN];
bool Instack[MAXN];
int N,M,top;
//d[u]>=d[v]+w(v,u);最长路
void Insert(int u,int v,int w)
{
	E[ecnt].v=v;
	E[ecnt].w=w;
	E[ecnt].next=head[u];
	head[u]=ecnt++;
}
void Init()
{
	int i,u,v,w;
	char s[2];
	memset(head,-1,sizeof(head));ecnt=0;
	for(i=1;i<=M;i++)
	{
		scanf("%s",s);
		if(s[0]=='P')
		{
			
			scanf("%d%d%d",&u,&v,&w);
			Insert(v,u,w);
			Insert(u,v,-w);//d[v]>=d[u]-w(u,v);
		}
		else
		{
			scanf("%d%d",&u,&v);
			Insert(v,u,1);//d[u]>=d[v]+w(v,u)
		}
	}
	for(i=1;i<=N;i++)//保证连通性
		Insert(0,i,0);
}
bool SPFA()
{
	int i,u,v,w;
	memset(cnt,0,sizeof(cnt));
	memset(Instack,false,sizeof(Instack));
	for(i=1;i<=N;i++)
		dis[i]=-INF;
	top=0;
	Stack[top++]=0;
	Instack[0]=true;
	cnt[0]=1;
	dis[0]=0;
	while(top)
	{
		u=Stack[--top];
		Instack[u]=false;
		cnt[u]++;
		if(cnt[u]>N) return false;
		for(i=head[u];i!=-1;i=E[i].next)
		{
			v=E[i].v;w=E[i].w;
			if(dis[v]<dis[u]+w)
			{
				dis[v]=dis[u]+w;
				if(!Instack[v])
				{
					Stack[top++]=v;
					Instack[v]=true;
				}
			}
		}
	}
	return true;
}
int main()
{
	while(scanf("%d%d",&N,&M)!=EOF)
	{
		Init();
		if(SPFA()) printf("Reliable\n");
		else printf("Unreliable\n"); 	
	}
return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

__简言

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值