本文出自: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;
}