P1250 种树

P1250 种树

题目描述

一条街的一边有几座房子。因为环保原因居民想要在路边种些树。路边的地区被分割成块,并被编号成1..N。每个部分为一个单位尺寸大小并最多可种一棵树。每个居民想在门前种些树并指定了三个号码B,E,T。这三个数表示该居民想在B和E之间最少种T棵树。当然,B≤E,居民必须记住在指定区不能种多于区域地块数的树,所以T≤E-B+l。居民们想种树的各自区域可以交叉。你的任务是求出能满足所有要求的最少的树的数量。

写一个程序完成以下工作:

输入输出格式

输入格式:

第一行包含数据N,区域的个数(0<N≤30000);

第二行包含H,房子的数目(0<H≤5000);

下面的H行描述居民们的需要:B E T,0<B≤E≤30000,T≤E-B+1。

输出格式:

输出文件只有一行写有树的数目

输入输出样例

输入样例#1: 
9
4
1 4 2
4 6 2
8 9 2
3 5 2
输出样例#1: 
5

选尽量少的的数,并且符合对每一个区间的要求。

典型的差分约束,因为是求最小值,所以要用最长路来求,我们设f[i]表示1~i个数中至少选的数的个数,对于每一个区间要求,我们就从B-1向E连一条长度为T的边,表示1~E中选的数的个数至少比1~B-1中选的数的个数多T,也就是B~E中至少选T个数。然而这样是不行的,因为题目中还有隐藏条件,首先十分显然的一个条件f[i+1]>=f[i],因为前i+1个数不可能比前i个数少,所以从i向i+1连一条权值为0的边,其次,对于每个数我们最多只能选一次,所以f[i+1]<=f[i]+1,但是这样不太好,我们移一下项f[i]>=f[i+1]-1,这样我们就要从i+1向i连一条边长为-1的边,最后从一号点跑一遍最长路就好了。

 

 1 #include<iostream>
 2 #include<string>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<cstdio>
 6 #include<stack>
 7 #include<queue>
 8 #define maxn 100005
 9 using namespace std;
10 
11 inline int read()
12 {
13     char c=getchar();
14     int x=1,res=0;
15     while(c<'0'||c>'9')
16     {
17         if(c=='-')
18         x=-1;
19         c=getchar();
20     }
21     while(c>='0'&&c<='9')
22     {
23         res=res*10+(c-'0');
24         c=getchar();
25     }
26     return x*res;
27 }
28 
29 struct edge
30 {
31     int next,to,dis;
32 }g[maxn<<1];
33 int n,m,aa,bb,cc,num;
34 int last[maxn],c[maxn],vis[maxn];
35 queue<int>q;
36 
37 void add(int from,int to,int dis)
38 {
39     g[++num].next=last[from];
40     g[num].to=to;
41     g[num].dis=dis;
42     last[from]=num;
43 }
44 
45 int main()
46 {
47     n=read();m=read();
48     for(int i=1;i<=m;i++)
49     {
50         aa=read();bb=read();cc=read();
51         add(aa-1,bb,cc);
52     }
53     for(int i=0;i<=n;i++)
54     {
55         add(i-1,i,0);
56         add(i,i-1,-1);
57         c[i]=-100000000;
58     }
59     c[0]=0;
60     q.push(0);
61     while(q.size())
62     {
63         int u=q.front();
64         q.pop();
65         vis[u]=0;
66         for(int i=last[u];i;i=g[i].next)
67         {
68             int v=g[i].to;
69             if(c[v]<c[u]+g[i].dis)
70             {
71                 c[v]=c[u]+g[i].dis;
72                 if(!vis[v])
73                 {
74                     vis[v]=1;
75                     q.push(v);
76                 }
77             }
78         }
79     }
80     printf("%d\n",c[n]);
81     return 0;
82 }
View Code

 

posted @ 2019-04-04 15:18  snowy2002  阅读(208)  评论(0编辑  收藏  举报