NKOI 1385 笨笨种西瓜

                                                           笨笨种西瓜

Time Limit:10000MS  Memory Limit:165536K
Total Submit:163 Accepted:82
Case Time Limit:1000MS

Description

笨笨种了一块西瓜地,但这块西瓜地的种植范围是一条直线的……
笨笨在一番研究过后,得出了m个结论,这m个结论可以使他收获的西瓜最多。
笨笨的结论是这样的:
从西瓜地B处到E处至少要种植T个西瓜,这个范围的收获就可以最大化。
笨笨不想那么辛苦,每个位置最多种一个西瓜,所以他想种植的西瓜尽量少,而又满足每一个所得的结论。

Input

第一行两个数n,m(0<n<=5000,0<=m<=3000),表示笨笨的西瓜地长n,笨笨得出m个结论。
接下来m行表示笨笨的m个结论,每行三个数b,e,t(1<=b<=e<=n,0<=t<=e-b+1)。

Output

输出笨笨最少需种植多少西瓜。

Sample Input

9 4
1 4 2
4 6 2
8 9 2
3 5 2

Sample Output

5

Hint

基本上来说,笨笨的西瓜地就是一条壮观的线……

这道题除了题目中给出的约束条件外其实还有两个题目中暗示的约束条件

那么所有的约束条件如下:

1:题目要求两个点(b和e)之间至少需要t个,就相当于Se-S(b-1)>=t
2:一个点至少要种0个,就是Si-S(i-1)>=0
3:一个点最多种1个(暂且这样认为),就是Si-S(i-1)<=1,移项得到S(i-1)-Si>=-1
然后再增加一个虚拟节点,到所有点的权值为0,再求最长路就行了

#include<cstdio>
#include<iostream>
#include<queue>
#define inf 2e9
using namespace std;
int n,m,cnt;
void _read(int &d){
	d=0;
	char t=getchar();
	for(d=0;t>='0'&&t<='9';t=getchar())d=(d<<3)+(d<<1)+t-'0';
}
int next[300005],end[300005],last[300005],len[300005];
int dis[300005];
bool f[300005];
queue<int>q;
void fst(int a,int b,int l){
	end[++cnt]=b;
	len[cnt]=l;
	next[cnt]=last[a];
	last[a]=cnt;
}
void spfa(){
	int i,y,t,x;
    for(i=n;i>=1;i--)dis[i]=-inf;
    q.push(0);
	f[0]=true;
	dis[0]=0;
    while(!q.empty()){
        x=q.front();
		q.pop();
		f[x]=false;
        t=last[x];
        while(t!=0){
           y=end[t];
           if(dis[x]+len[t]>dis[y]){
                  dis[y]=dis[x]+len[t];
                  if(!f[y]){
                      f[y]=true; 
                      q.push(y);
                  }
           } 
           t=next[t];
		}
    }
}
int main(){
	int i,e,b,c;
	_read(n);_read(m);
	for(i=n;i>=1;i--){
		fst(0,i,0);
		fst(i,i-1,-1);
		fst(i-1,i,0);
	}
	for(i=1;i<=m;i++){
		_read(b);
		_read(e);
		_read(c);
		fst(b-1,e,c);
	}
	spfa();
	cout<<dis[n];
}
一直wrong answer的话可以试一试这组数据

6 3
1 3 2
2 6 3
4 6 1

3


你可能感兴趣的:(NKOI 1385 笨笨种西瓜)