poj1364 King

链接:http://poj.org/problem?id=1364

题意:好吧,过了好几天才来写这个解题报告,我去。题意没忘,但是可能有点说不清了。不说了。。。

说一下学到的方法吧。

一、如果一个图可能不连通,则在运用SPFA时,先将所有的顶点入栈。这样做的目的是相当于虚设了一个源点,

该源点与所有的顶点连通(以便于检查是否存在负环)。而要注意的地方是,这个源点只是虚设的,若原先有N个

顶点,则在运用SPFA松弛(即把一个点的入栈)的次数要小于等于N-1次(也就是不包括虚设源点在内的)。


二、差分约束系统只适用于Xj-Xi<=w的情况,即是不等式!且必须要有等号!

如果遇到等式a-b=w,则可以变形为a-b>=w和a-b<=w,再来运用差分约束;

如果遇到等式a-b<w,就如这道题,要根据题意进行变形。因为题中给的是整数,

所以必有等式a-b<=w-1,这样就有了等号!!!就可以运用差分约束啦。

差分约束的题一定要灵活的变形。


#include<cstdio>
#include<cstring>
#include<queue>
#define MAXN 1005
#define MAXE 40000
using namespace std;
struct EDGE
{
   int to,w;
   int next;
}edge[MAXE];
int head[MAXN],dist[MAXN],vist[MAXN],inqu[MAXN];
int cnt;
void add(int u,int v,int w)
{
   edge[cnt].to=v;
   edge[cnt].w=w;
   edge[cnt].next=head[u];
   head[u]=cnt++;
}

int SPFA(int n)
{
	int i,k;
	memset(dist,0,sizeof(dist));
    memset(vist,0,sizeof(vist));
	memset(inqu,0,sizeof(inqu));
	queue<int> q;
	for(i=0;i<=n;i++)//将所有顶点入栈,使图连通,相当于构造虚源点
       q.push(i);
	while(!q.empty())
	{
	    k=q.front();
		q.pop();
		vist[k]=0;
		for(i=head[k];i!=-1;i=edge[i].next)
		{
		   if(dist[edge[i].to]>dist[k]+edge[i].w)
		   {
		     dist[edge[i].to]=dist[k]+edge[i].w;
			 if(!vist[edge[i].to])
			 {
			    vist[edge[i].to]=1;
				q.push(edge[i].to);
				inqu[edge[i].to]++;
				if(inqu[edge[i].to]>n)//第一次加入不算在内,一共n+1个顶点,所以最多只能松弛n次
					return 0;
			 }
		   }
		}
	}
	return 1;
}

int main()
{
	int n,m;
	int i,s,t,k;
	char op[5];
	while(scanf("%d",&n)&&n)
	{
		scanf("%d",&m);
		cnt=0;
		memset(head,-1,sizeof(head));
	   for(i=1;i<=m;i++)
	   {
	      scanf("%d%d%s%d",&s,&t,op,&k);
		  //scanf("%d%d%s%d",&s,&n,op,&k);
		  //一开始是这样的,n变量重名了,好像不止第一次犯这样的错误了
		  if(op[0]=='g')
		  {
			  add(t+s,s-1,-k-1);
		  }
		  else
		  {
			  add(s-1,t+s,k-1);
		  }
	   }
	   //for(i=0;i<=n;i++)
		   //add(n+1,i,0);
	   if(SPFA(n))
		   printf("lamentable kingdom\n");
	   else
		   printf("successful conspiracy\n");
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值