poj 1364 king (差分约束)

每行一个 n, m. n个序列 m个约束

设t为这个序列

(1)s n gt k     t[s+1] + t[s+2]+......+t[s+n] >k

(2)s n lt k     t[s+1] + t[s+2]+......+t[s+n] <k

设S[i]=t[1]+t[2]+t[3]+.....+t[i]

则(1):S[s+n] -S[s-1]>k -> S[s-1] -S[S+n] <-k

(2):S[s+n]-S[s-1]<k  

因为差分约束 是u-v<=k 小于号只需要 变成 u-v<=k-1。

建立超级源,spfa算法能退出就说明有解,否则无解。可以把每个dist值都设置为0,然后加入到队列中,这样就省去了建立源点添边的功夫。


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <vector>
#include <queue>
#define MAX_N 110
using namespace std;
struct edge{
	int to,w;
};
int n,m;
char choice[2][3]={"gt","lt"};
int vis[MAX_N];
bool inque[MAX_N];
int dist[MAX_N];
vector<edge> g[MAX_N];
void init_graph()
{
	for(int i=0;i<MAX_N;++i)
	{
		g[i].clear();
	}
}
void add_edge(int u,int v,int w)
{
	g[u].push_back((edge){v,w});
}
void add_constraint(int s,int t,char *str,int k)
{
	if(!strcmp(str,choice[0]))// S[s+t]-S[s-1]>k -> S[s-1]-S[s+t]<-k
		add_edge(s+t,s-1,-k-1);
	else add_edge(s-1,s+t,k-1);//S[s+t]-S[s-1]<k
}
bool spfa()
{
	memset(dist,0,sizeof(dist));
	memset(vis,0,sizeof(vis));
	memset(inque,0,sizeof(inque));
	queue<int> que;
	for(int i=0;i<=n;++i)
	{
		que.push(i);
		inque[i]=1;
	}
	while(!que.empty())
	{
		int u=que.front();que.pop();
		inque[u]=0;
		++vis[u];
		if(vis[u]>n) return false;
		for(int i=0;i<g[u].size();++i)
		{
			edge &e=g[u][i];
			if(dist[e.to]>dist[u]+e.w)
			{
				dist[e.to]=dist[u]+e.w;
				if(!inque[e.to])
				{
					que.push(e.to);
					inque[e.to]=1;
				}
			}
		}
	}
	return true;
}
int main()
{
	while(~scanf("%d",&n))
	{
		if(n==0)
			break;
		scanf("%d",&m);
		int s,t,k;
		char str[3];
		init_graph();
		for(int i=0;i<m;++i)
		{
			scanf("%d %d %s %d",&s,&t,&str,&k);
			add_constraint(s,t,str,k);
		}
		bool ans=spfa();
		if(ans)
			printf("lamentable kingdom\n");
		else printf("successful conspiracy\n");
	}
	return 0;
}


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