POJ--1364[King] 基础的差分约束

算法:差分约束

 

设Sum(i)=a1+a2+...+ai

任何一个序列

aSi + aSi+1 + ... + aSi+ni

可以变成 Sum(Si+ni)-Sum(Si-1)

然后如果是>号就两边乘-1,>号就变<号了

最后就是把<号变成<=号,因为所有数都是整数,把右边的数字-1就行了……

然后就化成标准的差分约束了

 

 

CODE:

/*AC代码:0ms*/
#include <iostream>
#include <queue>
#include <cstring>
using namespace std;
#define INF 0x7fffffff
#define MAXN 150
int map[MAXN][MAXN];//用来存约束图
bool flag[MAXN][MAXN];//flag[u][v]判断u->v是否有边
int visited[MAXN];//被松弛的次数
int d[MAXN];//d[v]表示源点到v点的最短路径
int N,M;//N是序列长度,M是约束条件个数
void init()//输入
{
	int si,ni,ki,i;
	int hx,hy,b;
	char w[3];
	memset(map,0,sizeof(map));
	memset(flag,false,sizeof(flag));
	N++;
	while(M--)
	{
		scanf("%d%d%s%d",&si,&ni,w,&ki);
		si++;//注意点,
		if(w[0]=='g')
		{
			hx=si-1;
			hy=si+ni;
			b=-ki-1;
		}
		else
		{
			hx=si+ni;
			hy=si-1;
			b=ki-1;
		}
		map[hx][hy]=b;
		flag[hx][hy]=true;
		//---------------//
		//这个也能A的
		//map[hy][hx]=b;
		//flag[hy][hx]=true;
	}
	for(i=1;i<=N;i++)//增加的0点于所有其他点都有权为0的边,目的确保整张图变通
		flag[0][i]=true;
}
bool Bellman_Ford()
{
	int i,temp;
	queue<int>Q;
	memset(visited,0,sizeof(visited));
	//memset(d,INF,sizeof(d));不能用
	for(i=1;i<=N;i++)
		d[i]=INF;
	d[0]=0;
	visited[0]++;
	Q.push(0);
	while(!Q.empty())
	{
		temp=Q.front();
		Q.pop();
		for(i=0;i<=N;i++)//用temp点更新其他点
		{
			if(flag[temp][i])
			{
				if(d[temp]+map[temp][i]<d[i])
				{
					d[i]=d[temp]+map[temp][i];
					Q.push(i);
					visited[i]++;
					if(visited[i]>N)//被松弛的次数超过N,说明存在负权回路
						return false;
				}
			}
		}
	}
	return true;
}
int main()
{
	while(scanf("%d",&N)!=EOF)
	{
		if(N==0)
			break;
		scanf("%d",&M);
		init();//输入函数
		if(Bellman_Ford())
			printf("lamentable kingdom\n");
		else
			printf("successful conspiracy\n");
	}
return 0;
}

你可能感兴趣的:(算法)