poj 1201(差分约束)

Intervals
Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 24948   Accepted: 9491

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

 

差分约束的区间约束问题。

题意:给定n(n <= 50000)个整点闭区间和这个区间中至少有多少整点需要被选中,每个区间的范围为[ai, bi],并且至少有ci个点需要被选中,其中0 <= ai <= bi <= 50000,问[0, 50000]至少需要有多少点被选中。

题解:这个题的话是典型的差分约束问题,s[i]代表 [0,i]区间内有多少被选中,所以d[i] - d[j-1] >= w ,但是由于 j是从 0 开始,所以下标要+1,还有就是对于某个区间 [i,i],0<=s[i+1]-s[i]<=1,这样的话根据约束条件就可以求出s->t的最长路即是最后的结果。

差分约束不等式的标准化:

如果给出的不等式有"<="也有">=",又该如何解决呢?很明显,首先需要关注最后的问题是什么,如果需要求的是两个变量差的最大值,那么需 要将所有不等式转变成"<="的形式,建图后求最短路;相反,如果需要求的是两个变量差的最小值,那么需要将所有不等式转化成">=",建图 后求最长路。

      如果有形如:A - B = c 这样的等式呢?我们可以将它转化成以下两个不等式:
A - B >= c      (1)
A - B <= c      (2)
       再通过上面的方法将其中一种不等号反向,建图即可。
       最后,如果这些变量都是整数域上的,那么遇到A - B < c这样的不带等号的不等式,我们需要将它转化成"<="或者">="的形式,即 A - B <= c - 1。
 
#include <iostream>
#include <cstdio>
#include <string.h>
#include <queue>
#include <algorithm>
#include <math.h>
using namespace std;
typedef long long LL;
const int INF = 999999999;
const int N = 160000;
const int M = 50005;
int n;
struct Edge{
    int v,w,next;
}edge[N];
int head[M];
int tot;
void init(){
    memset(head,-1,sizeof(head));
    tot = 0;
}
void addEdge(int u,int v,int w,int &k){
    edge[k].v = v,edge[k].w = w,edge[k].next = head[u],head[u] = k++;
}
bool vis[M];
int low[M];
int spfa(int s,int t){
    for(int i=s;i<=t;i++){
        vis[i] = false;
        low[i] = -INF;      ///求最长路初始值应该是 -INF
    }
    queue<int> q;
    low[s] = 0;
    q.push(s);
    while(!q.empty()){
        int u = q.front();
        q.pop();
        vis[u] = false;
        for(int k=head[u];k!=-1;k=edge[k].next){
            int v = edge[k].v,w = edge[k].w;
            if(low[v]<low[u]+w){
                low[v] = low[u]+w;
                if(!vis[v]){
                    vis[v] = true;
                    q.push(v);
                }
            }
        }
    }
    return low[t]-low[s];
}
int main(){
    while(scanf("%d",&n)!=EOF){
        init();
        int MIN = INF,MAX = -1;
        for(int i=1;i<=n;i++){
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            MAX = max(MAX,v+1);
            MIN = min(MIN,u);
            addEdge(u,v+1,w,tot);
        }
       // printf("%d %d
",MIN,MAX);
        for(int i=MIN;i<MAX;i++){
            addEdge(i,i+1,0,tot);
            addEdge(i+1,i,-1,tot);
        }
        printf("%d
",spfa(MIN,MAX));
    }
    return 0;
}
原文地址:https://www.cnblogs.com/liyinggang/p/5695818.html