• Hdu1384-Intervals(差分约束)


    Problem Description
    You are given n closed, integer intervals [ai, bi] and n integers c1, ..., cn.
    Write a program that:
    > reads the number of intervals, their endpoints and integers c1, ..., cn from the standard input,
    > computes the minimal size of a set Z of integers which has at least ci common elements with interval [ai, bi], for each i = 1, 2, ..., n,
    > writes the answer to the standard output
     
    Input
    The first line of the input contains an integer n (1 <= n <= 50 000) - the number of intervals. The following n lines describe the intervals. The i+1-th line of the input contains three integers ai, bi and ci separated by single spaces and such that 0 <= ai <= bi <= 50 000 and 1 <= ci <= bi - ai + 1.
    Process to the end of file.
     
    Output
    The output contains exactly one integer equal to the minimal size of set Z sharing at least ci elements with interval [ai, bi], for each i = 1, 2, ..., n.
     
    Sample Input
    5
    3 7 3
    8 10 3
    6 8 1
    1 3 1
    10 11 1
     
    Sample Output
    6
     
    题意:对于每个区间[a,b]至少要有c个元素,问集合里元素的最小个数。
     
    解析:差分约束,用Ti表示区间[0,i-1]有多少个元素在里面,则满足下面的条件
      Tb+1-Ta>=c
      0<=Ti+1-Ti<=1
      则建边(a,b+1,c),(i,i+1,0),(i+1,i,-1) 然后用spfa求得答案。注意这题用vector可能会超时。
     
    代码
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<iostream>
    #include<sstream>
    #include<algorithm>
    #include<utility>
    #include<vector>
    #include<set>
    #include<map>
    #include<queue>
    #include<cmath>
    #include<iterator>
    #include<stack>
    using namespace std;
    const int INF=1e9+7;
    const double eps=1e-7;
    const int maxn=50005;
    int N;
    struct edge
    {
        int u,v,w,next;
        edge(int u=0,int v=0,int w=0):u(u),v(v),w(w){next=-1; }
    }E[maxn*3];
    int head[maxn],dist[maxn];
    bool inq[maxn];
    queue<int> que;
    int spfa(int be,int en)
    {
        for(int i=be;i<=en;i++) dist[i]=-INF;
        dist[be]=0;
        memset(inq,false,sizeof(inq));
        while(!que.empty()) que.pop();
        que.push(be);
        while(!que.empty())
        {
            int u=que.front();  que.pop();
            inq[u]=false;
            for(int i=head[u];i!=-1;i=E[i].next)
            {
                int v=E[i].v,w=E[i].w;
                if(dist[v]<dist[u]+w)  //更新
                {
                    dist[v]=dist[u]+w;
                    if(!inq[v]){ inq[v]=true; que.push(v); }
                }
            }
        }
        return dist[en];
    }
    int main()
    {
        while(scanf("%d",&N)!=EOF)
        {
            memset(head,-1,sizeof(head));
            int u,v,w,cnt=0;
            int minv=INF,maxv=-INF;
            for(int i=0;i<N;i++)
            {
                scanf("%d%d%d",&u,&v,&w);  //建边(u,v+1,w);
                v++;
                E[++cnt]=edge(u,v,w);
                E[cnt].next=head[u];
                head[u]=cnt;
                minv=min(minv,u);
                maxv=max(maxv,v);
            }
            for(int i=minv;i<maxv;i++)
            {
                E[++cnt]=edge(i,i+1,0); //建边(i,i+1,0)
                E[cnt].next=head[i];
                head[i]=cnt;
                E[++cnt]=edge(i+1,i,-1); //建边(i+1,i,-1)
                E[cnt].next=head[i+1];
                head[i+1]=cnt;
            }
            printf("%d
    ",spfa(minv,maxv));
        }
        return 0;
    }
    View Code
  • 相关阅读:
    对搜狗浏览器的评价
    领扣(LeetCode)二叉树的所有路径 个人题解
    领扣(LeetCode)单词模式 个人题解
    领扣(LeetCode)最长公共前缀 个人题解
    领扣(LeetCode)设计哈希映射 个人题解
    领扣(LeetCode)寻找旋转排序数组中的最小值 个人题解
    领扣(LeetCode)最长和谐子序列 个人题解
    领扣(LeetCode)删除注释 个人题解
    领扣(LeetCode)检测大写字母 个人题解
    领扣(LeetCode)第三大的数 个人题解
  • 原文地址:https://www.cnblogs.com/wust-ouyangli/p/5661363.html
Copyright © 2020-2023  润新知