以前打了一道差分约束的模板,现在在专题中做到了,发现都不会。。。
1.
You are given n closed, integer intervals [ai, bi] and n integers c1, ..., cn.
Write a program that:
> reads the number of intervals, their endpoints and integers c1, ..., cn from the standard input,
> computes the minimal size of a set Z of integers which has at least ci common elements with interval [ai, bi], for each i = 1, 2, ..., n,
> writes the answer to the standard output.
Input
The first line of the input contains an integer n (1 <= n <= 50 000) - the number of intervals. The following n lines describe the intervals. The i+1-th line of the input contains three integers ai, bi and ci separated by single spaces and such that 0 <= ai <= bi <= 50 000 and 1 <= ci <= bi - ai + 1.
Process to the end of file
Output
The output contains exactly one integer equal to the minimal size of set Z sharing at least ci elements with interval [ai, bi], for each i = 1, 2, ..., n.
Sample Input
5
3 7 3
8 10 3
6 8 1
1 3 1
10 11 1
Sample Output
6
这题有很多的约束条件,题目中给出的是每一个区间的约束条件
a【x】表示1到x一共放了几个,那根据题目的约束条件,我们可以得出:
在x - y 区间 必须放 z个
a[y] - a[x-1] >= z -> a[x -1] - a[y] <= -z -> a[x-1] <= a[y] - z 这个对应的就是从 y到x-1建-z边权的边
但是, 要完全跑出这个差分约束系统的话, 还要加两个隐藏的限制条件:
i 到 i+1至少放0个,i 到 i+1 最多放1个:
a[i+1] - a[i] >= 0 ---> a[i] - a[i+1] <= 0 a[i+1] - a[i] <= 1 ---> a[i+1] <= a[i] + 1
差分约束除了搭建好约束条件以外, 还要注意边界搜索点的选择, 这题应该是选最小出现的一个数字,在它之前不必放了,所以把它当起点, 以最大的为终点, 因为比他大的不必放了。
#include<bits/stdc++.h>
using namespace std;
const int Maxn = 60000;
const int Emax = 160005;
int head[Maxn],cnt;
struct edge
{
int v,w,next;
}e[Emax];
void addedge(int cu,int cv,int cw)
{
cnt ++;
e[cnt].v = cv;
e[cnt].w = cw;
e[cnt].next = head[cu];
head[cu] = cnt;
}
int spfa (int n,int sta,int ee)
{
int vis[Emax],stack[Emax],dis[Emax],vn[Emax];
memset(vis,0,sizeof(vis));
memset(dis,0x7f,sizeof dis);
memset(vn,0,sizeof vn);
vn[sta]=1;
dis[sta] = 0;
vis[sta] = 1;
int top = 1;
stack[0] = sta;
while (top)
{
int u = stack[--top];
if(vn[u]>n)
return -0x7f7f7f7f;
vis[u] = 0;
for (int i = head[u];i != -1;i = e[i].next)
{
int v = e[i].v;
if (dis[v] > dis[u] + e[i].w)
{
dis[v] = dis[u] + e[i].w;
if (!vis[v])
{
vis[v] = 1;
vn[v]++;
stack[top++] = v;
}
}
}
}
return dis[ee];
}
int main ()
{
int n,m,v1,v2,cost;
int ml,md;
while(scanf("%d",&n)!=EOF)
{
cnt = 0;
memset (head,-1,sizeof(head));
int minn=0x3f3f3f3f;
int maxx=0;
for(int i=0;i<n;i++)
{
int u,v,lim;
scanf("%d%d%d",&u,&v,&lim);
u++;
v++;
maxx=max(maxx,v);
minn=min(minn,u);
addedge(v,u-1,-lim);
}
for(int i=minn-1;i<maxx;i++)
{
addedge(i+1,i,0);
addedge(i,i+1,1);
}
int ans=spfa(maxx-minn+2,maxx,minn-1);
printf("%d\n",-ans);
}
return 0;
}