码迷,mamicode.com
首页 > 其他好文 > 详细

【POJ】1364 King

时间:2015-07-29 21:27:56      阅读:131      评论:0      收藏:0      [点我收藏+]

标签:poj   查分约束系统   最短路   图论   特殊值法   

【解析】查分约束系统,最短路

[Problem]
S={a1,a2,a3,a4...ai...at},其中ai=a*si
现在给出多个不等式,使得ai+a[i+1]+a[i+2]+...+a[i+n]<ki或>ki
不等式这样描述:
给出四个参数i,n,s,d,i表示从序列的第i项开始,n表示序列长度为n,
当s="gt"时,表示A=ai+a[i+1]+...+a[i+n]>d,否则当s="lt"时,A<d。
询问是否有解。

[Analysis]
首先a*si可以不用管,谁知道a是多少呢,特殊值a=1就可以了。
由于是静态区间,考虑差分的思想,设tr[i]=∑a[j],1<=j<=i。
然后每一个约束条件都可以用差分的形式表示。
对于给定的i,n,s,d,
①当s="gt"时,
a[i]+a[i+1]+...+a[i+n]=tr[i+n]-tr[i-1]>d
∴tr[i+n]>d+tr[i-1]
∴tr[i-1]+(d+1)<=tr[i+n](式1)
建边(i-1,i+n,d+1)。
②当s="lt"
a[i]+...+a[i+n]=tr[i+n]-tr[i-1]<d
∴tr[i+n]+(1-d)<=tr[i-1]
建边(i+n,i-1,1-d)。(式2)
然后就求最长路看看有没有正权回路。(其实正负是差不多的,假如求负权回路就换一种建图方式)

至于为什么是正权回路而不是负权回路,这是为了满足每个约束条件,假如选了最短路,那么可能就会存在约束条件不满足。
用(式1)(式2)来理解。

接下来是求负权回路的方法。
求负权回路就用最短路的算法解决。
SPFA:设个数组vis,由于每个点不可能被松弛超过n次,所以当vis=n时就退出。
Bellman-Ford:O(n^3),稳定,代码短,具体就是枚举松弛次数,然后枚举两个点看看能不能松弛,最后再判断一次。

[Sum]
①回顾了查分约束系统的建图和求解。
②特别注意,用SPFA要n+1次的时候再判断不行。

[Code]
#include <cstdio>
#include <cstring>
#include <cstdlib>
using namespace std;

const int N=160;
const int MAX=20000000;

int n,m;
struct G
{
	int v,d,nxt;
}map[N];
int tt,hd[N];
int q[N],h,t,used[N],vis[N],d[N];

inline int read(void)
{
	int s=0,f=1; char c=getchar();
	for (;c<'0'||c>'9';c=getchar()) if (c=='-') f=-1;
	for (;'0'<=c&&c<='9';c=getchar()) s=s*10+c-'0';
	return s*f;
}

void ins(int u,int v,int d)
{
	map[++tt].v=v;
	map[tt].d=d;
	map[tt].nxt=hd[u];
	hd[u]=tt;
}

void build(void)
{
	int x,y,d; char c;
	tt=0; memset(hd,0,sizeof hd);
	
	for (int i=1;i<=m;i++)
	{
		scanf("%d%d %ct %d",&x,&y,&c,&d);
		if (c=='g') 
			ins(x+y,x-1,d+1);
		else ins(x-1,x+y,1-d);
	}
	
	for (int i=0;i<=n;i++) ins(n+1,i,0); n++;
}

void spfa(void)
{
	h=t=0;
	memset(vis,0,sizeof vis);
	memset(used,0,sizeof used);
	for (int i=0;i<=n;i++) d[i]=-MAX;
	
	d[n]=0,vis[n]=1,used[n]=1,q[t=1]=n;
	
	int k;
	for (;h^t;)
	{
		k=q[h=h%(n+1)+1];
		for (int r=hd[k];r;r=map[r].nxt)
			if (d[k]+map[r].d>d[map[r].v])
			{
				d[map[r].v]=d[k]+map[r].d;
				vis[map[r].v]++;
				if (vis[map[r].v]==n+1)
				{
					printf("successful conspiracy\n");
					return;
				}
				if (!used[map[r].v])
				{
					used[map[r].v]=1;
					q[t=t%(n+1)+1]=map[r].v;
				}
			}
		used[k]=0;
	}
	printf("lamentable kingdom\n");
}

int main(void)
{
	for (int cc=1;cc;cc++)
	{
		n=read();
		if (!n) break;
		m=read();
		build();
		spfa();
	}
	
	return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

【POJ】1364 King

标签:poj   查分约束系统   最短路   图论   特殊值法   

原文地址:http://blog.csdn.net/u013598409/article/details/47132759

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!