思路:
差分约束还是很神奇。
我的理解,本质是在对N个点排序,这么多点之间有距离关系,因为存在V这种模糊距离关系,所以距离关系有约束。
顾用差分约束系统来解决。
主要差分方程:
1.i-j>=w && i-j<=w (j-i>=-w);
2.i-j>=1;
spfa松弛方程
if(d[v]<d[u]+w)
d[v]=d[u]+w;
即d[i]始终保存节点i的取值范围的左边界。
然后则是检查负环,如果某个节点入队列次数>n,则有负环。(由bellman-ford得知边的松弛次数最大只需N-1).
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
#define Abs(a) ((a)>0?(a):(-(a)))
#define llong long long int
using namespace std;
const int N=1005,M=100005;
const int inf=(1<<30);
int n,m;
struct Edge
{
int v,w,next;
}edge[3*M];
int edgehead[N];
int _n;
int que[N*N];
int d[N];
bool vis[N];
int times[N];
void addedge(int u ,int v,int w)
{
edge[_n].v=v;
edge[_n].w=w;
edge[_n].next=edgehead[u];
edgehead[u]=_n++;
}
bool spfa(int s)
{
bool ans=true;
memset(vis,0,sizeof(vis));
memset(times,0,sizeof(times));
int head=1,tail=1;
que[tail++]=s;
times[s]=1;
vis[s]=true;
while(head<tail&&ans)
{
int now=que[head++];
vis[now]=false;
for(int i=edgehead[now];i;i=edge[i].next)
{
int v=edge[i].v;
int w=edge[i].w;
if(d[v]<d[now]+w)
{
d[v]=d[now]+w;
if(!vis[v])
{
if(times[v]>n)
{
ans=false;
break;
}
vis[v]=true;
que[tail++]=v;
times[v]++;
}
}
}
}
return ans;
}
void solve()
{
int s=n+1;
for(int i=1;i<=n;i++)
addedge(s,i,1);
if(spfa(s))
printf("Reliable\n");
else
printf("Unreliable\n");
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
_n=1;
memset(d,0,sizeof(d));
memset(edge,0,sizeof(edge));
memset(edgehead,0,sizeof(edgehead));
char cha;
int u,v;
for(int i=1;i<=m;i++)
{
scanf(" %c",&cha);
scanf("%d%d",&u,&v);
if(cha=='P')
{
int w;
scanf("%d",&w);
addedge(u,v,w);
addedge(v,u,-w);
}
else
{
addedge(u,v,1);
}
}
solve();
}
return 0;
}