• 【38.24%】【POJ 1201】Intervals


    Time Limit: 2000MS Memory Limit: 65536K
    Total Submissions: 25902 Accepted: 9905
    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 end points 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 <= 50000) – 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 <= 50000 and 1 <= ci <= bi - ai+1.
    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
    Source

    Southwestern Europe 2002

    【题目链接】:http://poj.org/problem?id=1201

    【题解】

    题意:
    给你m个条件ai bi ci;
    表示ai..bi这些整数在序列中至少出现了ci次;
    然后问你这个序列最少能由多少个数字组成;
    设d[i]表示1..i这些数字里面有多少个数字;
    则所给的m个条件可以写出
    d[bi]-d[ai]>=ci;
    然后就转化为差分约束的题了;
    考虑转化为最长路

    if (d[u]-d[v]<c)
        d[u] = d[v]+c;


    可以看到我们令d[u]=d[v]+c后实际上是让d[u]-d[v]=c;
    而原本d[u]-d[v]是小于c的,而如果d[u]再变大一点也可以满足d[u]-d[v]>c但是显然直接让d[u]-d[v]=c会使得d[u]更小;
    这样进行松弛操作后;整个d就是最小的了;
    所以对输入的ai bi ci;
    即d[bi]-d[ai]>=ci;
    则在ai与bi之间建一条由ai指向bi的单向边,边权为ci;
    又有0<=d[i]-d[i-1]<=1;->因为一个数字没必要出现两次;只可能有两种情况,出现一次或者不出现;

    d[i]-d[i-1]>=0
    d[i-1]-d[i]>=-1
    再根据这两个在i-1和i之间建边权为0的边,在i和i-1之间建边权为-1的边;
    然后一开始dis数组赋值为无穷小;然后从起点跑spfa即可;
    但是这样还不够;有些细节要做到位
    比如
    2
    1 2 1
    2 3 1
    这个输入
    如果我们单纯地在ai与bi之间建一条由ai指向bi的单向边,边权为ci;
    则会得到ans=2的错解;
    原因在于程序没办法判断1-2和2-3是否重合了;
    做法是把[ai,bi]换成[ai,bi+1);
    因为是整数,所以这样的做法是正确的;
    也即对于输入的ai bi ci;
    直接令bi++;
    然后再建边;
    找到最左的端点作为s,最右的端点作为t;则从s开始跑spafa;最后输出d[t];

    【完整代码】

    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #include <set>
    #include <map>
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <queue>
    #include <vector>
    #include <stack>
    #include <string>
    using namespace std;
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define LL long long
    #define rep1(i,a,b) for (int i = a;i <= b;i++)
    #define rep2(i,a,b) for (int i = a;i >= b;i--)
    #define mp make_pair
    #define pb push_back
    #define fi first
    #define se second
    
    typedef pair<int,int> pii;
    typedef pair<LL,LL> pll;
    
    void rel(LL &r)
    {
        r = 0;
        char t = getchar();
        while (!isdigit(t) && t!='-') t = getchar();
        LL sign = 1;
        if (t == '-')sign = -1;
        while (!isdigit(t)) t = getchar();
        while (isdigit(t)) r = r * 10 + t - '0', t = getchar();
        r = r*sign;
    }
    
    void rei(int &r)
    {
        r = 0;
        char t = getchar();
        while (!isdigit(t)&&t!='-') t = getchar();
        int sign = 1;
        if (t == '-')sign = -1;
        while (!isdigit(t)) t = getchar();
        while (isdigit(t)) r = r * 10 + t - '0', t = getchar();
        r = r*sign;
    }
    
    const int MAXM = (50000+100)*4;
    const int INF =-0x3f3f3f3f;
    const int dx[9] = {0,1,-1,0,0,-1,-1,1,1};
    const int dy[9] = {0,0,0,-1,1,-1,1,-1,1};
    const double pi = acos(-1.0);
    
    int w[MAXM],en[MAXM],fir[MAXM],nex[MAXM];
    int n,totm=0;
    
    void add(int x,int y,int z)
    {
        totm++;
        nex[totm] = fir[x];
        fir[x] = totm;
        en[totm] = y;
        w[totm] = z;
    }
    
    int main()
    {
        //freopen("F:\rush.txt","r",stdin);
        int s = 21e8,t=0;
        rei(n);
        rep1(i,1,n)
        {
            int x,y,z;
            rei(x);rei(y);rei(z);
            s = min(s,x);t=max(t,y+1);
            //dis[y]-dis[x]>=z
            add(x,y+1,z);
        }
        rep1(i,s,t)
        {
            add(i,i+1,0);
            add(i+1,i,-1);
        }
        int dis[MAXM];
        memset(dis,INF,sizeof(dis));
        dis[s] = 0;
        queue <int>dl;
        bool in[MAXM];
        dl.push(s);in[s] = true;
        while (!dl.empty())
        {
            int x = dl.front();
            in[x] = false;
            dl.pop();
            for (int temp = fir[x];temp;temp=nex[temp])
            {
                int y = en[temp];
                if (dis[y]<dis[x]+w[temp])
                {
                    dis[y] = dis[x] + w[temp];
                    if (!in[y])
                    {
                        in[y] = true;
                        dl.push(y);
                    }
                }
            }
        }
        cout << dis[t]<<endl;
        return 0;
    }
    
  • 相关阅读:
    [转]Angular2-组件间数据传递的两种方式
    [转]Angular4---部署---将Angular项目部署到IIS上
    [转]Angular开发(十八)-路由的基本认识
    [转]【Angular4】基础(一):脚手架 Angular CLI
    [转]【Angular4】基础(二):创建组件 Component
    [转]Angular项目目录结构详解
    [转]Ionic国际化解决方案
    [转]Angular CLI 安装和使用
    [转]nodejs之cordova 跨平台开发
    [转]Windows下配置Node.js和Cordova
  • 原文地址:https://www.cnblogs.com/AWCXV/p/7626881.html
Copyright © 2020-2023  润新知