【题意】
给出n个点和m条约束信息。信息表述为(P a b c)表示a在b北方距离c单位的位置,或者(V a b) 表示a在b的北方。问是否可能存在符合以上m个要求的点。
【输入格式】
第一行:两个整数n和m
接下来m行每行输入(P a b c)或者(V a b),意思如上所示。
多组数据。
【输出格式】
若存在这样的点则输出Reliable,不存在输出Unreliable。
【样例输入】
3 4
P 1 2 1
P 2 3 1
V 1 3
P 1 3 1
5 5
V 1 2
V 2 3
V 3 4
V 4 5
V 3 5
【样例输出】
Unreliable
Reliable
数据范围自己会原题看。。
caioj的数据有问题。。
对于这道题,我定义了一个数组f,表示这个点到最南方的距离
P的条件可以拆成两个
f[a]-f[b]>=c
f[a]-f[b]<=c
很明显,要是想同时满足,就必须要f[a]=f[b]+c
然后下面就是裸题了。。
然后这题有一个坑。。
就是有自环。。注意一下
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<queue>
#include<stack>
using namespace std;
const int N=50005;
struct qq
{
int x,y,z,last;
}s[100000*5];int num,last[N];
void init (int x,int y,int z)
{
num++;
s[num].x=x;s[num].y=y;s[num].z=z;
s[num].last=last[x];
last[x]=num;
}
int f[N];
bool in[N];
int du[N];
int n,m;
bool SPFA ()
{
stack<int> q;
memset(in,true,sizeof(in));
memset(f,0,sizeof(f));
for (int u=0;u<=n;u++) {du[u]=0;q.push(u);}
while (!q.empty())
{
int x=q.top();q.pop();in[x]=false;
du[x]++;
if (du[x]>n) return false;
for (int u=last[x];u!=-1;u=s[u].last)
{
int y=s[u].y;
if (f[y]<f[x]+s[u].z)
{
f[y]=f[x]+s[u].z;
if (in[y]==false)
{
in[y]=true;
q.push(y);
}
}
}
}
return true;
}
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int main()
{
while (scanf("%d%d",&n,&m)!=EOF)
{
num=0;memset(last,-1,sizeof(last));
for (int u=1;u<=m;u++)
{
char ss[5];
scanf("%s",ss);
if (ss[0]=='P')
{
int a=read(),b=read(),c=read();
//f[a]-f[b]>=c
//f[a]>=c+f[b]
init(b,a,c);
//f[a]-f[b]<=c
//f[b]>=f[a]-c
init(a,b,-c);
}
else
{
int a=read(),b=read();
//f[a]-f[b]>=1
//f[a]>=f[b]+1
init(b,a,1);
}
}
if (SPFA()) printf("Reliable\n");
else printf("Unreliable\n");
}
return 0;
}