• POJ 1201 Intervals 差分约束


    链接:http://poj.org/problem?id=1201

    Intervals
    Time Limit: 2000MS   Memory Limit: 65536K
    Total Submissions: 23123   Accepted: 8728

    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


    题意:

    给你n个闭区间

    【a,b】  及c

    要求区间内的点数必需要大于等于c

    点仅仅存在于区间内。

    然后问负无穷到正无穷最多有多少点。

    做法:

    我们从最左边到最右边。

    区间内最少有c个点,说明点(a-1)到b点 最少会添加c个点。

    也就是说  b-(a-1)>=c  转换下   (a-1)-b<=-c 就是差分约束的公式了。

    然后就是建边 建一条权值为-c   的b到(a-1)的边即可了。

    然后取最小的坐标x,取最大的坐标d。

    由于求最大值  所以得公式 d-(x-1)>=?

    加个负号, (x-1)-d<=-?

      ,所以最后最短路 计算 d点到(x-1)的最短距离。然后取负就是答案了。


    可是这样条件还不够。

    还有关键的是相邻点之间的建边。设相邻两点  (i) 和(i+1)   

    走到(i+1)数到的点数  肯定是比左边的(i)要大的 , 所以 (i+1)-(i)>=0  加个负号, (i)-(i+1)<=0

    而从(i)走到(i+1)最多仅仅添加了一个点。所以(i+1)-(i)<=1 。   

    所以还要建这些边,才干跑出最后的答案。


    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <limits.h>
    #include <malloc.h>
    #include <ctype.h>
    #include <math.h>
    #include <string>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    #include <stack>
    #include <queue>
    #include <vector>
    #include <deque>
    #include <set>
    #include <map>
     
    #define VM 60000
    #define EM 160005
    #define inf 0x7f7f7f7f
    int head[VM],ep;
    struct edge
    {
        int v,w,next;
    }e[EM];
    
    void addedge(int cu,int cv,int cw)
    {
        ep ++;
        e[ep].v = cv;
        e[ep].w = cw;
        e[ep].next = head[cu];
        head[cu] = ep;
    }
    
    int spfa (int n,int sta,int ee)
    {
        int vis[VM],stack[VM],dis[VM],vn[VM];
        memset(vis,0,sizeof(vis));
    	memset(dis,inf,sizeof dis); 
    	//for(int i=1;i<=n;i++)
    	//dis[i]=-inf;
    	memset(vn,0,sizeof vn);
    	vn[sta]=1;
        dis[sta] = 0;
        vis[sta] = 1;
        int top = 1;
        stack[0] = sta;
        while (top)
        { 
            int u = stack[--top];
    		if(vn[u]>n)
    			return -inf;
            vis[u] = 0;
            for (int i = head[u];i != -1;i = e[i].next)
            {
                int v = e[i].v;
                if (dis[v] > dis[u] + e[i].w)
                {
                    dis[v] = dis[u] + e[i].w;
                    if (!vis[v])
                    {
                        vis[v] = 1;
    					vn[v]++;
                        stack[top++] = v;
                    }
                }
            }
        } 
        return dis[ee];
    }
    int main ()
    { 
        int n,m,v1,v2,cost;
    	int ml,md;
    	while(scanf("%d",&n)!=EOF)
    	{
    		ep = 0;
    		memset (head,-1,sizeof(head));
    		
    
    
    		int minn=999999;
    		int maxx=0;
    		for(int i=0;i<n;i++)
    		{
    			int u,v,lim;
    			scanf("%d%d%d",&u,&v,&lim); //v-u<=lim
    			u++;
    			v++;
    
    			maxx=max(maxx,v);
    			minn=min(minn,u);
    			addedge(v,u-1,-lim);//   v-(u-1)>=lim   (u-v)<=lim
    		}
    		
    		//for(int i=0;i<50001;i++)
    		for(int i=minn-1;i<maxx;i++)
    		{ 
    			addedge(i+1,i,0);//(i)-(i+1)《=0   后面的点数大 
    			addedge(i,i+1,1);//(i+1)-(i)《=1   i+1 最多放一个 
    		}
    
    		/*
    		for(int i=1;i<n;i++)
    		{
    			addedge(i+1,i,0);//dian(i)- dian(i+1)<=0
    		}*/
    		int ans=spfa(maxx-minn+2,maxx,minn-1);
    		if(ans==-inf)
    			puts("-1");//负环 有矛盾条件
    		else if(ans==inf)//两者能够无线远
    			puts("-2");
    		else
    			printf("%d
    ",-ans);
    	}
    	return 0;
    }





  • 相关阅读:
    右键菜单:锁到任务栏丢失 修复
    检测到鼠标时自动禁用触摸板 (注:仅适用于个别笔记本)
    清除右键菜单CMD入口
    VBS编辑字段
    VBS创建数据表
    VBS创建数据库
    QTP操作论坛回复编辑框----webelement
    数字排序
    对应键盘的ASCII码(备忘)
    将字符串打乱输出
  • 原文地址:https://www.cnblogs.com/claireyuancy/p/6727613.html
Copyright © 2020-2023  润新知