码迷,mamicode.com
首页 > 其他好文 > 详细

「TYVJ1415」西瓜种植 - 差分约束

时间:2018-09-26 17:16:32      阅读:196      评论:0      收藏:0      [点我收藏+]

标签:ons   code   oid   efi   集合   包含   约束   false   push   

->戳我进原题

西瓜种植


时间限制:1000ms
空间限制:131072KiB


题目背景

笨笨:小西瓜,小西瓜~
路人甲:不会呀,这西瓜明明就大着啊……
笨笨:那……大西瓜,大西瓜~
路人甲:这么快就改口了……
笨笨:西瓜西瓜~可爱的西瓜~

题目描述

笨笨种了一块西瓜地,但这块西瓜地的种植范围是一条直线的……
笨笨在一番研究过后,得出了 \(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)\)

输出格式

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

提示

基本上来说,笨笨的西瓜地就是一条壮观的线……笨笨原创。
样例数据

输入样例 #1

9 4

1 4 2

4 6 2

8 9 2

3 5 2

输出样例 #1

5

思路

典型差分约束题,这个东西着实比较抽象,所以我调了好长时间才过2333。
这个题大概是这样的:

  • 给定 \(n\) 个闭区间 \([ai,bi](1≤n,0≤ai,bi≤50000)\)\(n\) 个整数 \(ci(1≤i≤n)\)

  • 你需要构造一个整数集合 \(Z\),使得 \(?i∈[1,n]\)\(Z\) 中满足 \(ai≤x≤bi\) 的整数 \(x\) 不少于 \(ci\)个。

  • 求这样的整数集合 \(Z\) 最少包含多少个数。

\(s[k]\) 表示 \(0\)\(k\) 之间最少选出多少个整数。根据题意,有 \(s[bi]?s[ai?1]≥ci\) 个,这很明显是一个差分约束系统的模型。
不过,我们还要增加一些隐含的条件,才能保证求出的解是有意义的:

1) \(s[k]?s[k?1]≥0\) \(0\)\(k\) 之间选出的书肯定在 \(0\)\(k?1\) 内。

2) \(s[k]?s[k?1]≤1\) 每个数只能被选一次。可变形为 \(s[k?1]?s[k]≥?1\)

代码

#include<cstdio>
#include<cctype>
#include<iostream>
#include<cstring>
#include<queue>
#define rg register
using namespace std;
inline int read(){
    rg int f = 0, x = 0;
    rg char ch = getchar();
    while(!isdigit(ch)) f |= (ch == '-'), ch = getchar();
    while( isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ 48), ch = getchar();
    return f? -x: x;
}
const int N = 5010;
const int inf = 0x7f7f7f7f;
int n, m, head[N], tot, dis[N], minn = inf, maxn = -inf;
bool vis[N];
struct edge{
    int to, nxt, w;
}e[N << 2];
inline void add(rg int u, rg int v, rg int w){
    e[++tot].nxt = head[u];
    e[tot].to = v;
    e[tot].w = w;
    head[u] = tot;
}
inline void spfa(){
    for(rg int i = minn; i <= maxn; ++i)    dis[i] = -inf;//dis一定要是负无穷 
    queue<int > q;
    dis[minn] = 0;
    q.push(minn);
    while(!q.empty()){
        int u = q.front();
        vis[u] = false;
        q.pop();
        for(rg int i = head[u]; i; i = e[i].nxt){
            int v = e[i].to;
            if(dis[v] < dis[u] + e[i].w){//注意约束条件的三角形不等式与计算最短路的不太一样 
                dis[v] = dis[u] + e[i].w;
                if(!vis[v]){
                    vis[v] = true;
                    q.push(v);
                }
            }
        }
    }
}
signed main(){
    n = read(), m = read();
    for(rg int i = 1; i <= m; ++i){
        int a = read(), b = read(), c = read();
        add(a - 1, b ,c);
        minn = min(minn, a - 1);
        maxn = max(maxn, b);
    }
    for(rg int i = minn; i <= maxn; ++i){   
        add(i, i + 1, 0);
        add(i + 1, i, -1);  
    }
    spfa();
    printf("%d", dis[maxn]);
    return 0;
}

「TYVJ1415」西瓜种植 - 差分约束

标签:ons   code   oid   efi   集合   包含   约束   false   push   

原文地址:https://www.cnblogs.com/horrigue/p/9707597.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!