【图论·习题】差分约束系统:Is the Information Reliable?

problem

The galaxy war between the Empire Draco and the Commonwealth of Zibu broke out 3 years ago. Draco established a line of defense called Grot. Grot is a straight line with N defense stations. Because of the cooperation of the stations, Zibu’s Marine Glory cannot march any further but stay outside the line.

A mystery Information Group X benefits form selling information to both sides of the war. Today you the administrator of Zibu’s Intelligence Department got a piece of information about Grot’s defense stations’ arrangement from Information Group X. Your task is to determine whether the information is reliable.

The information consists of M tips. Each tip is either precise or vague.

Precise tip is in the form of P A B X, means defense station A is X light-years north of defense station B.

Vague tip is in the form of V A B, means defense station A is in the north of defense station B, at least 1 light-year, but the precise distance is unknown.

银河系中有n个防御站排成一条直线,给定m条信息,每条信息的格式如下:

P A B X代表A站在B站北方X光年处。

V A B 代表A站在B站北方,而且距离至少为1光年。

问是否存在这样的一个防御战排列满足上述要求,是输出Reliable,否输出Unreliable。

Solution

这道题因为根据上述不等关系,可以确定答案是查分约束系统。

设d[i]表示第i个防御站的位置。

按照查分约束系统的常规操作,列出不等式:

根据第V操作,可以得到: d [ A ] − d [ B ] ≥ 1 → d [ B ] − d [ A ] ≤ − 1. d[A]-d[B]≥1→d[B]-d[A]≤-1. d[A]d[B]1d[B]d[A]1.

此时A向B连一条权值为-1的有向边。

根据P操作,可以得到, d [ A ] − d [ B ] = x → x ≤ d [ A ] − d [ B ] ≤ x d[A]-d[B]=x→x≤d[A]-d[B]≤x d[A]d[B]=xxd[A]d[B]x

像这样的等式,我们可以用两个不等式来限制,使得最后的公共部分只有一个数字,这种等式转不等式的方法在差分约束中及其常见。

最后,因为图不是联通的,我们需要连接一个虚拟远点0保证图的连通性,使得每一个点都能被遍历到。

代码如下:

#include<iostream>
#include<queue>
#include<vector>
#include<cstdio>
#include<cstring>
using namespace std;
#define Mp make_pair
char c;
int n,m,A,B,V;
int d[2000],v[2000],tot[20000];
vector<pair<int,int> >a[2000]; 
void work()
{
	queue<int>q;
	for (int i=0;i<2000;++i) a[i].clear();
	for (int i=1;i<=m;++i)
	{
		scanf("\n%c",&c);
		if (c=='P')
		{
			scanf("%d%d%d",&A,&B,&V);
			a[B].push_back(Mp(A,V));
			a[A].push_back(Mp(B,-V));
		}
		if (c=='V')
		{
			scanf("%d%d",&A,&B);
			a[A].push_back(Mp(B,-1));
		}
	}
	for (int i=1;i<=n;++i) a[0].push_back(Mp(i,1));
	
	memset(tot,0,sizeof(tot));
	memset(v,0,sizeof(v));
	memset(d,0x3f,sizeof(d));
	d[0]=0,v[0]=1;
	q.push(0);
	while (q.size())
	{
		int p=q.front();
		q.pop();
		v[p]=0;
		for (int i=0;i<a[p].size();++i)
		{
			int np=a[p][i].first,val=a[p][i].second;
			if (d[p]+val<d[np])
			{
				d[np]=d[p]+val;
				if (!v[np])
				{
					q.push(np);
					tot[np]++;
					v[np]=1;
					if (tot[np]>n) 
					{
						cout<<"Unreliable\n";
						return;
					}
				}
			}
		}
	}
	cout<<"Reliable\n";
}
int main(void)
{
	while (scanf("%d%d",&n,&m)==2) work();
	return 0;
} 
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值