zoukankan      html  css  js  c++  java
  • POJ1201 Intervals <差分约束系统>

    Intervals

    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个区间,试确定一个集合使得对于i=1..n,第i个区间内至少有ci个数,并使得此集合尽量小,输出最小大小。

    题解:
    首先用前缀和。sum[i]表示从1到i中共选出多少个数到集合中。这样对于集合[ai,bi],有sum[bi]-sum[ai-1]>=ci,于是我们可以从点ai-1到bi连一条权值为ci的边。因为题意是要满足所有的边,所以我们需要找最长路。
    此题有一些细节问题。首先,找最长路需要起点和终点,我们需要找到这些集合覆盖的范围,即找到左端点(其实应该是左端点-1)的最小值s和右端点的最大值t,找s到t的最大值。此外,光有上述的那些边时无法构成一个连通图的,所以我们需要找一些隐含条件。可以发现有sum[i]-sum[i-1]>=0,sum[i]-sum[i-1]<=1,为了保持一致,应将后面的式子转化为大于等于,即sum[i-1]-sum[i]>=-1,这样对于i=s+1~t,从i-1到i连接一条权值为0的路,从i到i-1连接一条权值为-1的路,之后就可以直接用SPFA找最长路了。

    最后附上AC代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <queue>
    #define MAX_N 50000
    using namespace std;
    int n, cnt, s, t, pre[MAX_N+5], dis[MAX_N+5];
    struct node {int v, c, nxt;} E[MAX_N*3+5];
    void insert(int u, int v, int c) {
    	E[++cnt].v = v, E[cnt].c = c;
    	E[cnt].nxt = pre[u], pre[u] = cnt;
    }
    void SPFA() {
    	queue <int> que;
    	bool inque[MAX_N+5];
    	memset(dis, 128, sizeof(dis));
    	memset(inque, 0, sizeof(inque));
    	dis[s] = 0;
    	que.push(s), inque[s] = true;
    	while (!que.empty()) {
    		int u = que.front();
    		for (int i = pre[u]; i; i = E[i].nxt) {
    			int v = E[i].v, c = E[i].c;
    			if (dis[u]+c > dis[v]) {
    				dis[v] = dis[u]+c;
    				if (!inque[v])	que.push(v), inque[v] = true;
    			}
    		}
    		que.pop(), inque[u] = false;
    	}
    }
    int main() {
    	while (scanf("%d", &n) != EOF) {
    		cnt = 0, s = 50000, t = 0;
    		memset(pre, 0, sizeof(pre));
    		memset(E, 0, sizeof(E));
    		for (int i = 0; i < n; i++) {
    			int u, v, c;
    			scanf("%d%d%d", &u, &v, &c);
    			insert(u, v+1, c);
    			s = min(s, u);
    			t = max(t, v+1);
    		}
    		for (int i = s; i < t; i++)	insert(i, i+1, 0), insert(i+1, i, -1);
    		SPFA();
    		printf("%d
    ", dis[t]);
    	}
    	return 0;
    }
    
  • 相关阅读:
    【PowerDesigner】【2】将工具栏显示出来
    【PowerDesigner】【1】简单介绍
    【服务器】【Windows】【4】删除Windows系统中不想要的服务
    【Java】【8】StringUtils中isNotEmpty和isNotBlank的区别
    【Java】【7】枚举类
    hdu 1285
    Codeforces Round #198 (Div. 2) —— D
    Codeforces Round #198 (Div. 2) —— C
    Codeforces Round #198 (Div. 2) —— B
    Codeforces Round #198 (Div. 2) —— A
  • 原文地址:https://www.cnblogs.com/AzraelDeath/p/7561740.html
Copyright © 2011-2022 走看看