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]≥1→d[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]=x→x≤d[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;
}