差分约束基本题型:
给出一个序列,1至n这n个数字,然后已知从i 到j 的数字和至多a、至少b,给出这么一组,然后求每个数字最小为多少,或者求总和最小为多少。
于是构造,设s[i]为0到i的和,那么s[1]即为第一个数字,s[2]-s[1]即为第二个数字,于是给出的条件转换为:
s[i] - s[j] >= b
s[i] - s[j] <= a
s[i] - s[i-1] >= 0
s[i] - s[i-1] <= V (*如果是1到n这n个容器,每个容器有容量,或者特殊情况n个布尔值,那么需要加上这个限制条件)
题目大意:
给出一些区间[ai,bi]和每个区间最少需要几个点ci,然后问总共最少需要几个点满足所有区间的要求。比如给出1 5 2和 4 6 2,就是说1到5需要2个点,4到6需要2个点,那么最少需要2个点就可以满足条件了。
思路:
这个就是上面说的布尔值了,抽象成
s[bi] - s[ai-1] >= ci
s[i] - s[i-1] >= 0
s[i] - s[i-1] <= 1
注意边界是s[bi]-s[ai-1],避免重复。
然后进行差分约束求最长路。另外,此题不需要判断是否不满足条件,即存在环。另外,全部初始化为0即可,或者除起始点为0其余点为-INF,然后松弛的时候判断一下。
PS:昨天去网上搜资料,打印资料,看了一天的差分约束,理解了大概思路,没实践。今天怀着忐忑的心情,建图,写SPFA,写完之后对比测试数据,一样。交第一遍,RE,立马将数组开到50010,第二遍,RE,想起昨天网上看的资料,一般数组大小都是4*SIZE左右,于是果断将数组开到200010,看Status,AC了。还得多写写差分约束的题。
有关差分约束的简单证明:http://hi.baidu.com/jffifa/item/ef628c50d37345dcd58bac44
差分约束求的是什么?http://whiteath.weebly.com/1/post/2010/11/2.html
ZOJ差分约束具体应用:http://whiteath.weebly.com/3/post/2010/12/zoj-150814551420.html
CODE:
#include <cstdio>
#include <queue>
using namespace std;
const int SIZE = 50010;
const int INF = 0x3f3f3f3f;
int u[4*SIZE], v[4*SIZE], w[4*SIZE], next[4*SIZE];
int first[SIZE], d[SIZE];
int cnt, Min, Max;
void read_graph(int u1, int v1, int w1)
{
u[cnt] = u1; v[cnt] = v1; w[cnt] = w1;
next[cnt] = first[u[cnt]];
first[u[cnt]] = cnt;
cnt++;
}
void spfa(int src)
{
queue<int> q;
bool inq[SIZE] = {0};
for(int i = Min; i <= Max; i++) d[i] = (i == Min)? 0:-INF;
q.push(Min);
while(!q.empty())
{
int x = q.front(); q.pop();
inq[x] = 0;
for(int e = first[x]; e!=-1; e = next[e]) if(d[v[e]] < d[x]+w[e]) //最长路三角不等式
{
d[v[e]] = d[x] + w[e];
if(!inq[v[e]])
{
inq[v[e]] = 1;
q.push(v[e]);
}
}
}
printf("%d\n", d[Max]);
}
void init()
{
memset(u, 0, sizeof(u));
memset(v, 0, sizeof(v));
memset(w, INF, sizeof(w));
memset(first, -1, sizeof(first));
memset(next, 0, sizeof(next));
Min = INF;
Max = 0;
}
int main()
{
int n;
while(~scanf("%d", &n))
{
init();
cnt = 0;
while(n--)
{
int x, y, z;
scanf("%d%d%d", &x, &y, &z);
x++; y++;
Max = max(Max, y);
Min = min(Min, x-1);
read_graph(x-1, y, z);
}
for(int i = Min; i <= Max; i++)
{
read_graph(i-1, i, 0);
read_graph(i, i-1, -1);
}
spfa(Min);
}
}