题意:给定n个左右均为闭的区间[a,b],及一个对应的c,意思是从[a,b]中至少要选c个数,现在问要使得所有n个区间均满足上面的条件,至少需要选几个点。
思路:假定t[I]代表是否选取,1为选取,0为不选.设si = t[0]+t[1]+...+t[I]。则s[I-1] - s[I]>=-1,s[I]-s[I-1]>=0.因为s[I]-s[I-1]等于0或1.s[b]-s[a-1]>=c.由这三个条件建图
差分约束:https://wenku.baidu.com/view/b061cb986bec0975f465e234.html
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
const int maxn = 50010;
const int INF = 1<<30;
int n,num,left;
struct edge
{
int from,to,w;
};
vector<edge> edges;
vector<int> g[maxn];
int inq[maxn],d[maxn],cnt[maxn];
void addedge(int from,int to,int w)
{
edges.push_back(edge{from,to,w});
int m = edges.size();
g[from].push_back(m-1);
}
bool bellman_ford(int s)
{
queue<int> q;
q.push(s);
memset(cnt,0,sizeof(cnt));
memset(inq,0,sizeof(inq));
for(int i=0;i<=num;i++)
d[i]=INF;
d[s]=0;
inq[s]=1;
while(!q.empty())
{
int u = q.front();q.pop();
inq[u]=0;
for(int i=0;i<g[u].size();i++)
{
edge &e=edges[g[u][i]];
if(d[e.to]>d[u]+e.w)
{
d[e.to]=d[u]+e.w;
if(!inq[e.to])
{
q.push(e.to);inq[e.to]=1;
if(++cnt[e.to]>n)return false;
}
}
}
}
return true;
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
for(int i=left-1;i<=num;i++)
g[i].clear();
edges.clear();
num=-(1<<30);
left=1<<30;
for(int i=0;i<n;i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
addedge(b,a-1,-c);
if(b>num)num=b;
if(a<left)left=a;
}
for(int i=left;i<=num;i++)
{
addedge(i,i-1,0);
addedge(i-1,i,1);
}
bellman_ford(num);
printf("%d\n",-d[left-1]);
}
}