zoj2770Burn the Linked Camp(差分约束)

题目请戳这里

题目大意:刘备有n个军营,陆逊要烧之,所以要事先估计刘备有多少人。已知刘备第i个军营不超过ci个人,通过侦查,陆逊有m个消息,表示刘备第i个军营到第j个军营至少有k人,现在要估计刘备军队至少多少人。

题目分析:差分约束。根据题意可以整理出一些不等式组:

1。首先每个军营的人数0<=ai<=ci,用si表示前i个军营人数总和。那么就有si - si-1 >= 0即si-1 - si <= 0,以及si - si-1 <= ci

2。第i个军营到第j个军营至少k人,sj - si-1 >= k,即si-1 - sj <= -k

3。第i个军营到第j个军营人数不能超过sigma(ci~cj),即sj - si-1 <= sigma(ci~cj)

这样差分约束系统就建立好了。再看要求什么。

题目要求估计刘备军队人数,即sn-s0,那么以n为原点求最短路,就能满足上面的约束关系,那么答案就是n到0的距离取反,即-s[0]。

详情请见代码:

#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 1005;
const int M = 10005;
const int INF = 0x3f3f3f3f;
int n,m;
int c[N];
int head[N];
struct node
{
    int to,val,next;
}g[M<<2];
int num;
bool ok;
bool flag[N];
int dis[N];
int queue[N];
int in[N];
int front,rear;
void build(int s,int e,int v)
{
    g[num].to = e;
    g[num].val = v;
    g[num].next = head[s];
    head[s] = num++;
}
void SPFA()
{
    int i,j;
    for(i = 0;i <= n;i ++)
    {
        flag[i] = false;
        dis[i] = INF;
        in[i] = 0;
    }
    dis[n] = 0;
    flag[n] = true;
    in[n] ++;
    front = rear = 0;
    queue[rear ++] = n;
    while(front < rear)
    {
        int u = queue[front ++];
        flag[u] = false;
        for(i = head[u];i != -1;i = g[i].next)
        {
            if(dis[g[i].to] > dis[u] + g[i].val)
            {
                dis[g[i].to] = dis[u] + g[i].val;
                if(flag[g[i].to] == false)
                {
                    if(in[g[i].to] == n - 1)
                    {
                        ok = true;
                        return;
                    }
                    in[g[i].to] ++;
                    flag[g[i].to] = true;
                    queue[rear ++] = g[i].to;
                }
            }
        }
    }
}
int main()
{
    int i,j,k;
    while(scanf("%d%d",&n,&m) != EOF)
    {
        num = 0;
        memset(head,-1,sizeof(head));
        c[0] = 0;
        for(i = 1;i <= n;i ++)
        {
            scanf("%d",&c[i]);
            build(i - 1,i,c[i]);
            c[i] += c[i - 1];
            build(i,i - 1,0);
        }
        while(m --)
        {
            scanf("%d%d%d",&i,&j,&k);
            build(i - 1,j,c[j] - c[i - 1]);
            build(j,i - 1,-k);
        }
        ok = false;
        SPFA();
        if(ok)
            puts("Bad Estimations");
        else
            printf("%d\n",dis[n] - dis[0]);
    }
    return 0;
}
//50ms	676k


你可能感兴趣的:(图论,差分约束)