UVA 515 King题解

写一篇差分约束系统的题解。

洛谷题目链接
POJ题目链接

差分约束相信大家都会,就是写出不等式,然后将题目转化为图上问题即可

这道题目的特殊之处就是用到一个超级源点,超级源点就是这个点与所有的边连一条边权为零的边,便于跑 SPFA (当然跑 bellman 也不拦着你)。

不等式

根据题目找一下不等式

第一种是 \(a_m+\cdots+a_n > W\)

然后转化为前缀和 \(S[n]-S[m-1] \geq W+1\)

第二种是 \(a_m+\cdots+a_n < W\)

转化为前缀和 \(S[n]-S[m-1] \leq W-1\)

然后都转化为大于等于 \(S[n]-S[m-1] \geq 1-W\)

既然是大于等于,再求最长路,判断是否符合就行了。

这道题就是差分约束系统判断是否存在的一类问题,这一类问题有两种情况(当然此题只涉及一种),在此列举一下:

有负环:无解

无约束:无数解

Code:

#include<bits/stdc++.h>
using namespace std;
const int maxn=1010;
const int INF=0x3f3f3f3f;
int head[maxn],cnt;
struct node
{
	int nxt,v,w;
}e[maxn<<1];
void add(int u,int v,int w)
{
	e[cnt].v=v;
	e[cnt].w=w;
	e[cnt].nxt=head[u];
	head[u]=cnt++;
}
int dis[maxn],num[maxn];
bool vis[maxn];
bool spfa(int s)//判负环
{
	memset(vis,false,sizeof(vis));
	memset(dis,-INF,sizeof(dis));
	memset(num,0,sizeof(num));
	vis[s]=true;
	dis[s]=0; queue<int>q;
	q.push(s);
	while(!q.empty())
	{
		int u=q.front();
		q.pop();
		vis[u]=false;
		for(int i=head[u];~i;i=e[i].nxt)
		{
			int v=e[i].v;
			if(dis[v]<dis[u]+e[i].w)
			{
				dis[v]=dis[u]+e[i].w;
				if(!vis[v])
				{
					vis[v]=true;
					q.push(v);
					if(++num[v]>s+1) return false;
				}
			}
		}
	}
	return true;
}
int main()
{
	int n;
	while(scanf("%d",&n)==1,n)
	{
		int m;
		memset(head,-1,sizeof(head));
		cnt=0;
		scanf("%d",&m);
		for(int i=0;i<m;++i)
		{
			int a,b,w;
			char ch[10];
			scanf("%d %d %s %d",&a,&b,ch,&w);
			if(ch[0]=='g') 
			{
				add(a-1,a+b,w+1);//第一种情况
			}
			else 
			{
				add(a+b,a-1,1-w);//第二种情况 
			}
		}
		for(int i=0;i<=n;++i)
		{
			add(n+1,i,0);//设置超级源点,可以为0号点,也可以为n+1号点
		}
		if(spfa(n+1)) puts("lamentable kingdom");
		else puts("successful conspiracy");
	}
	return 0;
}
posted @ 2022-07-11 08:06  离弦  阅读(28)  评论(0编辑  收藏  举报