题目链接:http://poj.org/problem?id=2983
题意:给M个不等式,判断是否存在可行解。
对差分约束的理解
摘自大牛博客:差分约束系统,对于bellman和spfa来说,解差分的不同在于,对于不连通图bellman能直接处
理,而spfa不能,需要加入超级源(一个到所有点都有一条长度为0的边的点),并把超级源作为起点,才能保
证在扩展过程中到达每个点。否则差分约束系统的部分内容就不会被检测到。当然也不是所有题遇到这种不连
通的情况都可以使用超级源。因为这种超级源相当于把不同的连通分支在数轴上的起点都平移到了原点。如题
目有特殊要求,则可以对不同的连通分支分别做单独处理。
优化版469ms
#include <iostream> #include <cstdlib> #include <cstdio> #include <cstring> #include <queue> #include <algorithm> const int N = 210; const int maxn = 2000; const int maxm = 201010; const int inf = 1e8; #define MIN INT_MIN #define MAX 1e6 #define LL long long #define init(a) memset(a,0,sizeof(a)) #define FOR(i,a,b) for(int i = a;i<b;i++) #define max(a,b) (a>b)?(a):(b) #define min(a,b) (a>b)?(b):(a) using namespace std; struct node{ int u,v,w; }edge[maxm]; int bnum,dis[maxn]; bool Bellman(int s,int t) { init(dis); bool flag; FOR(i,1,t+1) { flag = 0; FOR(j,0,bnum) { if(dis[edge[j].v] > dis[edge[j].u] - edge[j].w) { dis[edge[j].v] = dis[edge[j].u] - edge[j].w; flag = 1; } } if(!flag) return 0; } return 1; } int main() { int n,m,s,t; int a,c,b; char str[5]; while(scanf("%d%d",&n,&m)!=EOF) { bnum = 0; FOR(i,0,m) { scanf("%s",str); if(str[0]=='P') { scanf("%d%d%d",&a,&b,&c); edge[bnum].u = a;edge[bnum].v = b; edge[bnum++].w = c; edge[bnum].u = b;edge[bnum].v = a; edge[bnum++].w = -c; } else { scanf("%d%d",&a,&b); edge[bnum].u = a;edge[bnum].v = b; edge[bnum++].w = 1; } } s = 1,t = n; bool flag = Bellman(s,t); (flag==1)?puts("Unreliable"):puts("Reliable"); } return 0; }
不优化2750ms
#include <iostream> #include <cstdlib> #include <cstdio> #include <cstring> #include <queue> #include <algorithm> const int N = 210; const int maxn = 2000; const int maxm = 201010; const int inf = 1e8; #define MIN INT_MIN #define MAX 1e6 #define LL long long #define init(a) memset(a,0,sizeof(a)) #define FOR(i,a,b) for(int i = a;i<b;i++) #define max(a,b) (a>b)?(a):(b) #define min(a,b) (a>b)?(b):(a) using namespace std; struct node{ int u,v,w; }edge[maxm]; int bnum,dis[maxn]; bool Bellman(int s,int t) { init(dis); FOR(i,1,t+1) { FOR(j,0,bnum) { if(dis[edge[j].v] > dis[edge[j].u] - edge[j].w) { dis[edge[j].v] = dis[edge[j].u] - edge[j].w; } } } FOR(j,0,bnum) { if(dis[edge[j].v] > dis[edge[j].u] - edge[j].w) { dis[edge[j].v] = dis[edge[j].u] - edge[j].w; return 1; } } return 0; } int main() { int n,m,s,t; int a,c,b; char str[5]; while(scanf("%d%d",&n,&m)!=EOF) { bnum = 0; FOR(i,0,m) { scanf("%s",str); if(str[0]=='P') { scanf("%d%d%d",&a,&b,&c); edge[bnum].u = a;edge[bnum].v = b; edge[bnum++].w = c; edge[bnum].u = b;edge[bnum].v = a; edge[bnum++].w = -c; } else { scanf("%d%d",&a,&b); edge[bnum].u = a;edge[bnum].v = b; edge[bnum++].w = 1; } } s = 1,t = n; bool flag = Bellman(s,t); (flag==1)?puts("Unreliable"):puts("Reliable"); } return 0; }