题链:
http://poj.org/problem?id=2983
题解:
差分约束。
1).对于条件(P u v w),不难发现反映到图上就是:
$dis[u]-dis[v]=w$,所以添加两条边:
u → v : -w
v → u : w
2).对于条件(V,u,v),反映到图上即为:
$dis[u]-dis[v]>=1$,所以添加一条边:
v → u : 1
建好图后,dfs版spfa判一下是否存在正环就好了。
(出现正环代表Unreliable,否则就是Reliable)
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#define MAXN 1050
#define MAXM 100050
using namespace std;
struct Edge{
int to[MAXM*2],nxt[MAXM*2],val[MAXM*2],head[MAXN],ent;
void Reset(){ent=2;memset(head,0,sizeof(head));}
void Adde(int u,int v,int w){
to[ent]=v; val[ent]=w; nxt[ent]=head[u]; head[u]=ent++;
}
}E;
int dis[MAXN],mark[MAXN];
int N,M;
bool dfs(int u){
if(mark[u]) return 1; mark[u]=1;
for(int i=E.head[u];i;i=E.nxt[i]){
if(dis[E.to[i]]>=dis[u]+E.val[i]) continue;
dis[E.to[i]]=dis[u]+E.val[i];
if(dfs(E.to[i])) return mark[u]=0,1;
}
return mark[u]=0,0;
}
bool check(){
memset(dis,0,sizeof(dis));
for(int i=1;i<=N;i++) if(dfs(i)) return 0;
return 1;
}
int main(){
char cmd; int u,v,w;
while(~scanf("%d%d",&N,&M)){
E.Reset();
for(int i=1;i<=M;i++){
scanf(" %c%d%d",&cmd,&u,&v);
if(cmd=='P'){
scanf("%d",&w);
E.Adde(v,u,w);
E.Adde(u,v,-w);
}else E.Adde(v,u,1);
}
if(check()) printf("Reliable\n");
else printf("Unreliable\n");
}
return 0;
}