P1385笨笨种西瓜 | |
|
问题描述
笨笨种了一块西瓜地,但这块西瓜地的种植范围是一条直线的……
笨笨在一番研究过后,得出了m个结论,这m个结论可以使他收获的西瓜最多。
笨笨的结论是这样的:
从西瓜地B处到E处至少要种植T个西瓜,这个范围的收获就可以最大化。
笨笨不想那么辛苦,所以他想种植的西瓜尽量少,而又满足每一个所得的结论。
输入格式
第一行两个数n,m(0<n<=5000,0<=m<=3000),表示笨笨的西瓜地长n,笨笨得出m个结论。
接下来m行表示笨笨的m个结论,每行三个数b,e,t(1<=b<=e<=n,0<=t<=e-b+1)。
输出格式
输出笨笨最少需种植多少西瓜。
样例输入
9 4
1 4 2
4 6 2
8 9 2
3 5 2
样例输出
5
提示
基本上来说,笨笨的西瓜地就是一条壮观的线……
【题解】
1、思路:需要满足众多不等式,of course 差分约束。
2、具体;
(1)一条线>>前缀和数组dis;
(2)满足dis[i]-dis[i-1]<=1(每个地方只能种一个);
(3)满足dis[i]-dis[i-1]>=0(肯定不能小于零);
(4)满足dis[e]-dis[b-1]>=t(题意);
(5)加虚拟源点跑最长路吧,少年!!!!!
【代码】
#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
const int inf=999999999;
int n,m,dis[5005],st;
bool f[5005];
queue<int>q;
int tot=0,lastt[5005],endd[15005],len[15005],nextt[15005];
void addd(int x,int y,int z)
{
tot++;
endd[tot]=y;
len[tot]=z;
nextt[tot]=lastt[x];
lastt[x]=tot;
}
void spfa(int s)
{
int i,x,t,y,l;
for(i=0;i<=n;i++)
dis[i]=-inf,f[i]=false;
while(!q.empty())q.pop();
dis[s]=0,f[s]=true,q.push(s);
while(!q.empty())
{
x=q.front();
f[x]=false;
q.pop();
t=lastt[x];
while(t)
{
y=endd[t];
if(dis[y]<dis[x]+len[t])
{
dis[y]=dis[x]+len[t];
if(!f[y])
{
q.push(y);
f[y]=true;
}
}
t=nextt[t];
}
}
}
int main()
{
scanf("%d%d",&n,&m);
st=n+1;
int i,b,e,t;
for(i=1;i<=m;i++)
{
scanf("%d%d%d",&b,&e,&t);
addd(b-1,e,t);
}
for(i=1;i<=n;i++)
addd(i,i-1,-1),addd(st,i,0),addd(i-1,i,0);
addd(st,0,0);
spfa(st);
printf("%d\n",dis[n]);
return 0;
}