思路:运用spfa算法求差分约束问题
差分约束相关知识点:
这里设的d[i]代表【0,i)这个区间取值的个数,那么在 【a b】区间 中取出至少c个数可表示为 d[b+1]-d[a]>c,这就构成了一种边,
另外我们易知 (其实开始我完全不知道。。。) 0=<d[i]-d[i-1]<=1 ,这就又构造了两条边,接下来就是用spfa算法求解了,注意到题目中说一定有解 ,所以这里不用判负圈
#include <iostream>
#include <cstring>
#include <stdio.h>
#include <queue>
#define INF 0x3f3f3f3f
using namespace std;
int n,begin,end,e;
int v[155000],u[155000],w[155000],d[155000],first[155000],nex[155000];
int vis[155000];
void add(int x,int y,int z)
{
v[e]=y;
w[e]=z;
nex[e]=first[x];
first[x]=e++;
}
void spfa()
{
for(int i=begin;i<=end;i++)
{
d[i]=-INF;
}
d[begin]=0;
queue<int>q;
q.push(begin);
vis[begin]=1;
while(!q.empty())
{
int tmp=q.front();
vis[tmp]=0;
q.pop();
for(int i=first[tmp];i!=-1;i=nex[i])
{
if(d[v[i]]<d[tmp]+w[i])
{
d[v[i]]=d[tmp]+w[i];
if(!vis[v[i]])
q.push(v[i]);
vis[v[i]]=1;
}
}
}
}
int main()
{
//freopen("in.txt","r",stdin);
while(scanf("%d",&n)!=EOF)
{
e=0;
int a,b,c;
begin=INF;
end=-INF;
memset(first,-1,sizeof(first));
memset(vis,0,sizeof(vis));
memset(w,0,sizeof(w));
for(int i=0;i<n;i++)
{
scanf("%d%d%d",&a,&b,&c);
begin=min(begin,a);
end=max(end,b+1);
add(a,b+1,c);
}
for(int i=begin;i<end;i++)
{
add(i,i+1,0);
add(i+1,i,-1);
}
spfa();
printf("%d\n",d[end]);
}
}