zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    Centos7.x做开机启动脚本
    贝叶斯方法之一
    R程序包
    c#调用R
    感悟--不可抗拒的行为
    IP等级
    词语
    关于editplus设置java和c#
    csc命令
    editplus配置csharp
  • 原文地址:https://www.cnblogs.com/allh123/p/2997118.html
Copyright © 2011-2022 走看看