题链:
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 "); else printf("Unreliable "); } return 0; }