ZOJ2770 Burn the Linked Camp (差分约束与最短路)

本文出自:http://blog.csdn.net/svitter


题意:给你n个营地,每个营地最多Cn个人,然后告诉你i~j个营地中,最少有k个人。让你求一共有多少个士兵。

本题目为差分约束,差分约束的关键就在于解线性不等式。

把线性不等式转换为图中的松弛操作思想。

简单的例子:dis[v]  <= dis[u] + (u, v) 如是。

做这个题目的时候其实没有仔细想想为什么,就只是单纯的列出不等式然后导入到边的关系,就认为可以A出了。

然后很容易就做错了- -

不等式为:

s [ i  - 1 ]  <= s [ j ] + ( -k );(2)

s [ i  - 1 ]  <= s [ i ] (3)

s [ i ]  <= s [ i  - 1 ] + c [ i ];  (4)

如是。s [ i ]表示从1到i一共有多少个士兵。Xi  = s [ i ] - s [ i - 1 ] ;


此时,要选择n作为源点。为什么?

如果选择0为源点,即dis [ n ] -  dis [ 0 ] <= dis(0 , n) 

因为dis [ 0 ] 是 0 ,所以求出dis [ n ] <=dis(0 , n);

如果选择n为源点,即dis [ 0 ]  -dis [ n ] <= dis(n , 0) 即dis[ 0 ] >=dis[ n ] - dis(n , 0) 

因为dis [ n ] = 0, 则dis [ 0 ] >= - dis(n , 0);

第一个求出的是全部士兵最大值,第二个求出的是全部士兵最小值。

也正是媛姐所说:http://blog.csdn.net/zxy_snow/article/details/6173375(我不认识她 = =)

//from : blog.csdn.net/svitter


#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

#define INF 0x1f1f1f1f
//k<2^31

struct Edge
{
    int u;
    int v;
    int w;
};

Edge edge[15000];
int res[1001];

bool bellman(int n, int m, int src)
{
    memset(res, 0x1f, sizeof(res));
    res[n] = 0;
    int i, j;
    for(i = 0; i <= n; i++)
    {
        for(j = 0; j < m; j++)
        {
            if(res[edge[j].u] < INF && res[edge[j].u] + edge[j].w < res[edge[j].v])
                res[edge[j].v] = res[edge[j].u] + edge[j].w;
        }
    }
    for(i = 0; i < n; i++)
    {
        for(j = 0; j < m; j++)
        {
            if(res[edge[j].u] < INF && res[edge[j].u] + edge[j].w < res[edge[j].v])
                return 1;
        }
    }
    return 0;
}

void ace()
{
    //work point;
    int i, j, k;
    //case
    int n, m, num;
    //num
    int u, v, w;
    while(~scanf("%d%d", &n, &m))
    {
        num = 1;
        for(i = 0; i < n; i ++)
        {
            scanf("%d", &w);
            //res[num-1] <= res[num] + 0
            edge[i].u = num;
            edge[i].v = num - 1;
            edge[i].w = 0;

            //res[num] <= res[num-1] + Ci
            edge[i+n].u = num - 1;
            edge[i+n].v = num;
            edge[i+n].w = w;
            num++;
        }
        m += 2 * n;
        for(i = 2 * n; i < m; i++)
        {
            scanf("%d%d%d", &u, &v, &w);
            //res[u-1] <= res[v] - (v, u);
            edge[i].u = v;
            edge[i].v = u - 1;
            edge[i].w = -w;
        }
        if(bellman(n, m, 1))
            printf("Bad Estimations\n");
        else
            printf("%d\n", -res[0]);
    }//end of n
}

int main()
{
    ace();
    return 0;
}



转载于:https://my.oschina.net/u/1017188/blog/333727

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值