zoukankan      html  css  js  c++  java
  • POJ 1201 Intervals【差分约束】

    传送门:http://poj.org/problem?id=1201

    题意:

    有n个如下形式的条件:a_i,b_i,c_i,表示在区间[a_i, b_i]内至少要选择c_i个整数点.问你满足以上所有条件,最少需要选多少个点?

    思路:第一道差分约束题,有关差分约束知识详见https://blog.csdn.net/whereisherofrom/article/details/78922648(个人感觉这个博主写的挺好的)

    s_x表示从区间[0,x]中选择的整数点个数,则有s_{b_i}-s_{a_i-1}>=c_i
ightarrow s_{b_i+1}-s_{a_i}>=c_i(因为a_i>=0,会出现数组下标为-1的情况),如果只靠这个式子是无法得出答案的,题中还有隐藏的约束0<=s_{i+1}-s_i<=1即是s_{i+1}-s_i>=0s_i-s_{i+1}>=-1,题中要求最小值,所以用spfa跑一遍最长路即可。

    代码:

    #include<iostream>
    #include<cstdio>
    #include<queue>
    using namespace std;
    const int maxn = 50005;
    const int INF = 0x3f3f3f3f;
    
    int tot;
    struct node
    {
        int to;
        int next;
        int w;
    };
    node edges[maxn * 3];
    
    int head[maxn];
    int d[maxn];
    bool vis[maxn];
    
    void add_edges(int u, int v, int w)
    {
        edges[++tot].to = v;
        edges[tot].w = w;
        edges[tot].next = head[u];
        head[u] = tot;
    }
    
    int l = 50005;
    int r = -1;
    
    void spfa()
    {
        for(int i = l; i <= r; i++)
            vis[i] = false, d[i] = -INF;
        d[l] = 0;
        queue<int>q;
        q.push(l);
        while(!q.empty())
        {
            int x = q.front();
            q.pop();
            vis[x] = false;
            for(int i = head[x]; i; i = edges[i].next)
            {
                node v = edges[i];
                if(d[v.to] < d[x] + v.w)
                {
                    d[v.to] = d[x] + v.w;
                    if(!vis[v.to])
                    {
                        vis[v.to] = true;
                        q.push(v.to);
                    }
                }
            }
        }
    }
    int main()
    {
        int n;
        scanf("%d", &n);
        for(int i = 1; i <= n; i++)
        {
            int a, b, c;
            scanf("%d%d%d", &a, &b, &c);
            add_edges(a, b + 1, c); 
            r = max(r, b + 1);	  //求区间右端点
            l = min(l, a);        //求区间左端点
        }
        for(int i = l; i < r; i++)
        {
            add_edges(i + 1, i, -1);
            add_edges(i, i + 1, 0);
        }
        spfa();
        cout << d[r] << endl;
    }
  • 相关阅读:
    三极管8050和8550对管的参数
    三极管9014 管脚
    水深不语,人稳不言
    编译结果分析
    三母运算符
    C语言关键词解释
    51定时器初值的计算
    聪明人都在远离手机虚假繁荣的“人脉”关系
    每段路,都是一种领悟
    你的灯亮着吗读后感二
  • 原文地址:https://www.cnblogs.com/yyaoling/p/12260412.html
Copyright © 2011-2022 走看看