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 }

 

posted on 2013-04-03 00:36  allh123  阅读(173)  评论(0编辑  收藏  举报

导航