种树(codevs 1768)

题目描述 Description

为了绿化乡村,H村积极响应号召,开始种树了。

H村里有n幢房屋,这些屋子的排列顺序很有特点,在一条直线上。于是方便起见,我们给它们标上1~n。树就种在房子前面的空地上。

同时,村民们向村长提出了m个意见,每个意见都是按如下格式:希望第li个房子到第ri个房子的房前至少有ci棵树。

因为每个房屋前的空地面积有限,所以每个房屋前最多只能种ki棵树

村长希望在满足村民全部要求的同时,种最少的树以节约资金。请你帮助村长。

输入描述 Input Description

输入第1行,包含两个整数nm

第2行,有n个整数ki

 第3~m+1行,每行三个整数lirici

输出描述 Output Description

输出1个整数表示在满足村民全部要求的情况下最少要种的树。村民提的要求是可以全部满足的

样例输入 Sample Input

4 3

3 2 4 1

1 2 4

2 3 5

2 4 6

样例输出 Sample Output

8

数据范围及提示 Data Size & Hint

对于30%的数据,0<n≤100,0<m≤100,ki=1;

对于50%的数据,0<n≤2,000,0<m≤5,000,0<ki≤100;

对于70%的数据,0<n≤50,000,0<m≤100,000,0<ki≤1,000;

对于100%的数据,0<n≤500,000,0<m≤500,000,0<ki≤5,000。

/*
  差分约束
*/
#include<cstdio>
#include<cstring>
#include<iostream>
#include<queue>
#define M 500010
using namespace std;
int head[M],dis[M],vis[M],n,m,cnt;
struct node
{
    int v,t,pre;
};node e[M*3];
void add(int x,int y,int z)
{
    ++cnt;
    e[cnt].v=y;
    e[cnt].t=z;
    e[cnt].pre=head[x];
    head[x]=cnt;
}
void spfa(int s,int t)
{
    memset(dis,0x3f3f3f3f,sizeof(dis));
    queue<int> q;
    q.push(s);vis[s]=1;dis[s]=0;
    while(!q.empty())
    {
        int u=q.front();
        q.pop();vis[u]=0;
        for(int i=head[u];i;i=e[i].pre)
          if(dis[e[i].v]>dis[u]+e[i].t)
          {
              dis[e[i].v]=dis[u]+e[i].t;
              if(!vis[e[i].v])
              {
                  vis[e[i].v]=1;
                  q.push(e[i].v);
            }
          }
    }
    printf("%d",-dis[t]);
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        int z;scanf("%d",&z);
        add(i-1,i,z);
        add(i,i-1,0);
        //因为题目要求一定能满足所有要求,所以要从i到i-1建一条无权边
    }
    for(int i=1;i<=m;i++)
    {
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        add(y,x-1,-z);
    }
    spfa(n,0);
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/harden/p/5883114.html