zoj 1508 差分约束 Bellman-Ford

Intervals

Time Limit: 10 Seconds      Memory Limit: 32768 KB

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


Source: Southwestern Europe 2002

参考了《数与图的完美结合--浅析差分约束系统》,by 张威:http://pan.baidu.com/share/link?shareid=508660&uk=2720516383&fid=743287535

对属于区间[ai, bi]的任意元素,按属于于不属于题述序列关系,可定义如下映射:

t=0,表某元素不在序列中;1,表在序列中。

则可令Si= 从ai-1到bi,求和(t),即Si表该区间[ai,bi]中在序列的元素个数。至此,不难构造不等式(组):

S(bi)-S(ai-1)>=ci;另外由任意S(i)与S(i-1)的关系也可得:

0<=S(i)-S(i-1)<=1; 转化为:

S(ai-1) - S(bi) <= -ci

S(i-1) - S(i) <= 0

S(i) - S(i-1) <= 1

于是就可以直接建图用bellmanford算法了,但答案是多少呢?这里我不很清楚,可能是这样建图产生负权边,然后求相对值吧。论文给出的是d[最大节点标号]-d[最小节点标号,即0].

AC代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<string>
 5 #include<cmath>
 6 #include<vector>
 7 #include<cstdlib>
 8 #include<algorithm>
 9 #include<queue>
10 
11 using namespace std;
12 
13 #define LL long long
14 #define ULL unsigned long long
15 #define UINT unsigned int
16 #define MAX_INT 0x7fffffff
17 #define MAX_LL 0x7fffffffffffffff
18 #define MAX(X,Y) ((X) > (Y) ? (X) : (Y))
19 #define MIN(X,Y) ((X) < (Y) ? (X) : (Y))
20 
21 #define MAXN 66666
22 #define MAXM 200000
23 #define INF 100000
24 
25 struct edge{
26     int u,v,nxt,w;
27 }e[MAXM];
28 int cc,h[MAXN];
29 int inq[MAXN],d[MAXN];
30 int ans;
31 
32 inline void add(int u, int v, int w){
33     e[cc]=(edge){u,v,h[u],w};
34     h[u]=cc++;
35 }
36 
37 queue<int> q;
38 int bford(int s, int n){
39     int u,i,w,v;
40     while(!q.empty()) q.pop();  q.push(s);
41  //   memset(cnt, 0, sizeof(cnt));    cnt[s]=1;
42     memset(inq, 0, sizeof(inq));    inq[s]=1;
43     for(i=0; i<n; i++) d[i]=INF;    d[s]=0;
44     while(!q.empty()){
45         u=q.front();    q.pop();    inq[u]=0;
46         for(i=h[u]; i!=-1; i=e[i].nxt){
47             v=e[i].v;
48             w=e[i].w;
49             if(d[v]>d[u]+w){
50                 d[v]=d[u]+w;
51                 if(!inq[v]){
52     //                if(++cnt[v]>n) return 1;
53                     q.push(v);
54                     inq[v]=1;
55                 }
56             }
57         }
58     }
59     ans=d[s-1]-d[0];            // 结果不是d[s-1]么?。。。
60     return 0;
61 }
62 
63 #define POINT(x) ((x) < 0 ? 0 : (x) )
64 
65 int main(){
66 //  freopen("C:\\Users\\Administrator\\Desktop\\in.txt","r",stdin);
67     int n;
68     while(scanf(" %d",&n)==1){
69         int a,b,c;
70         int i,ub=0;
71         cc=0;
72         memset(h, -1, sizeof(h));
73         for(i=0; i<n; i++){
74             scanf(" %d %d %d",&a,&b,&c);
75             add(b, POINT(a-1), -c);         // S(bi) - S(ai-1) <= C(i) --如果a-1<0,则用0代替a-1,仍满足,此时0表示ai-1项不存在
76             ub=MAX(ub, b);                  // 记录最大点编号
77         }
78         ub++;
79         for(i=1; i<ub; i++){
80             add(i, i-1, 0);                 // S(i-1) - S(i) <= 0
81             add(i-1, i, 1);                 // S(i) - S(i-1) <= 1
82         }
83         for(i=0; i<ub; i++) add(ub, i, 0);  // S(ub+1) - i <= 0  --虚拟源点,编号ub+1
84 
85         bford(ub, ub+2);                    // 共有ub+2个点
86         printf("%d\n", ans);
87     }
88     return 0;
89 }
View Code

 

转载于:https://www.cnblogs.com/ramanujan/p/3280245.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值