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 }

 

转载于:https://www.cnblogs.com/allh123/archive/2013/04/03/2997118.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
该资源内项目源码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。 该资源内项目源码是个人的课程设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值