Burn the Linked Camp ZOJ 2770 差分约束系统 SPFA
这个题是建立一个差分约束系统的模型,设前i个营的实际总人数为si,则根据题意,可得每个营的人数s[i] - s[i-1] <= c[i], i = 1,2......n
他会给m个估计,s[j] - s[i-1] >= k,即s[i-1] - s[j] <= -k.
然后还有一个约束就是每个营的人数要大于等于0, 即s[i] - s[i-1] >= 0,也就是说 s[i-1] - s[i] <=0.
考虑一个三角形,任意两边只和大于第三边,再加上三条线共线,换种说法:
已知一个源点,源点到每个点都有路,整个图连通,有边<u,v>从源点到顶点v的最短路一定<= 到源点到顶点 u的最短路加上边长edge[u][v],结论显然正确,
反证法,否则就不是从源点到v点的最短路径了。这样就有d[v] - d[u] <= edge[u][v],对每个方程构造出一条边,用SPFA求到每个顶点的最短路,所有的值求出来后就是差分约束系统的一个可行解。如果中间出现了负权值回路,证明该系统无解,我也不是很了解为什么。这个源点是自己加进去的,它到每个顶点都有边,且权值为0.
求s[n] - s[0],就是求用上述方法构造出的图的顶点n到顶点0的最短路。
贴代码:
View Code
1 #include <cstdio> 2 #include <cstring> 3 #include <queue> 4 #include <iostream> 5 #define MAXN 1005 6 #define INF 1000000 7 using namespace std; 8 struct ArcNode 9 { 10 int v; 11 long long int w; 12 } edge[MAXN][MAXN]; 13 int arcnum[MAXN]; 14 int n; 15 long long int num[MAXN]; 16 int count[MAXN]; 17 bool s[MAXN]; 18 long long int SPFA(int uo,int vo) 19 { 20 int i,j; 21 queue<int > Q; 22 memset(s,false,sizeof(s)); 23 memset(count,0,sizeof(count)); 24 for(i=0; i<=n; i++) 25 num[i] = INF; 26 num[uo] = 0; 27 s[uo] = true; 28 count[uo] = 1; 29 Q.push(uo); 30 bool flag = false; 31 while(!Q.empty() && !flag) 32 { 33 int te = Q.front(); 34 Q.pop(); 35 s[te] = false; 36 for(j=0; j< arcnum[te]; j++) 37 { 38 if(num[te] + edge[te][j].w < num[edge[te][j].v]) 39 { 40 num[edge[te][j].v] = num[te] + edge[te][j].w ; 41 if(!s[edge[te][j].v]) 42 { 43 Q.push(edge[te][j].v); 44 s[edge[te][j].v] = true; 45 count[edge[te][j].v]++; 46 if(count[edge[te][j].v] > n) //一个顶点重复入队列超过n次,有负权值回路 47 { 48 flag = true; 49 break; 50 } 51 } 52 } 53 } 54 } 55 if(flag) return 1; 56 else return -num[vo]; 57 } 58 int main() 59 { 60 // freopen("in.cpp","r",stdin); 61 int m; 62 while(~scanf("%d%d",&n,&m)) 63 { 64 int i; 65 int ci; 66 int xi,xj; 67 long long int k; 68 memset(arcnum,0,sizeof(arcnum)); 69 for(i=1; i<= n; i++) 70 { 71 scanf("%d",&ci); 72 edge[i-1][arcnum[i-1]].v = i; 73 edge[i-1][arcnum[i-1]].w = ci; 74 arcnum[i-1]++; 75 edge[i][arcnum[i]].v = i-1; 76 edge[i][arcnum[i]].w = 0; 77 arcnum[i]++; 78 } 79 for(i=0; i<m; i++) 80 { 81 scanf("%d%d",&xi,&xj); 82 cin>>k; 83 edge[xj][arcnum[xj]].v = xi-1; 84 edge[xj][arcnum[xj]].w = -k; 85 arcnum[xj]++; 86 } 87 long long int temp = SPFA(n,0); 88 if( temp == 1) 89 printf("Bad Estimations\n"); 90 else 91 cout<<temp<<endl; 92 } 93 return 0; 94 }