思路:
差分约束还是很神奇。
我的理解,本质是在对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; }