题意:给出若干条线段,和一个公共点数c,要求一个集合,集合中的元素和该线段的公共点数不得小于c
问这个集合最少有几个点
解法:最小值查分约束 找出形如x-y>=k的不等式 然后建图为 y->x建边 边权为k
令f(x)=∑(0~x-1) 那么我们可以得到 1=>[i,i]>=0 [a,b]>=c
然后建图就可以了
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
#define inf 1e7
#define maxn 50010
struct edge{
int v,w,next;
}e[maxn*3];
int dis[maxn],vis[maxn],head[maxn];
int cnt;
void add(int u,int v,int w)//有向静态邻接表
{
e[cnt].v=v;
e[cnt].w=w;
e[cnt].next=head[u];
head[u]=cnt++;
}
int st,en;
void init()
{
cnt=0;
st=inf,en=-inf;
memset(head,-1,sizeof head);
memset(vis,0,sizeof vis);
}
void spfa()
{
for(int i=st;i<=en;++i){dis[i]=-inf;}
queue<int>q;
q.push(st);
dis[st]=0;vis[st]=1;
int cur,v;
while(!q.empty()){
cur=q.front();
q.pop();
vis[cur]=0;
for(int i=head[cur];i!=-1;i=e[i].next){
v=e[i].v;
if(dis[v]<dis[cur]+e[i].w){
dis[v]=dis[cur]+e[i].w;
if(!vis[v]){
q.push(v); //未在队列中
vis[v]=1;
}
}
}
}
}
//最小值:x-y>=k y->x w:k
int main()
{
int n;while(~scanf("%d",&n)){
init();
int a,b,c;
while(n--){
scanf("%d%d%d",&a,&b,&c);
add(a,b+1,c); // [a,b]>=c-->f(b+1)-f(a)>=c
st=min(a,st);
en=max(en,b+1);
}
for(int i=st;i<=en;++i){
add(i,i+1,0); // 0=<[i,i+1]<=1
add(i+1,i,-1); // f(i+1)-f(i)>=0 f(i)-f(i+1)>=-1
}
spfa();
printf("%d\n",dis[en]);
}
return 0;
}