Initiate

Call A Spade a Spade
posts - 14, comments - 3, trackbacks - 0, articles - 0
  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

POJ 1201 Intervals 差分约束+spfa

Posted on 2010-04-03 00:23 Initiate 阅读(3330) 评论(3)  编辑 收藏 引用 所属分类: 贪心图论

Intervals

Time Limit: 2000MS

Memory Limit: 65536K

Total Submissions: 8965

Accepted: 3318

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

 

思路:

题目的转换真的非常非常巧妙,让我再来梳理一下。本题的题意是给了我们一些区间,然后告诉每个区间中至少需要取Ci个数。求出满足n个条件的集合C的最少的元素个数。

首先第一个转化,是找到一个合理的表示。用ti表示每一个数,如果有用就是1,否则是0。吧S(i+1)定义成S(i+1)=sigma(tj)(1<=j<=i)也就是。S[i+1]表示从0到i有多少个数是需要的。

因此,题目中的条件可以表示成S[bi+1]>=S[ai]+Ci//至少要Ci个

这与bellman中的松弛操作时很像的。因此可以看成一些点

有D[v]>=D[u]+w(u,v)

上式对任何u成立,所以v应该是里面最大的,若D[v]<D[u]+w(u,v)则D[v]=D[u]+w(u,v)

于是。可以从ai和bi+1连一条线,它的长度是ci

这里只有这些条件还是不够的,还要加上两个使其满足整数性质的条件

1>=s[i+1]-s[i]>=0

有了这么多条件,使其自然构成了一个差分约束系统。

用spfa算法得到一个最长路,第一个到最后一个节点的最长路即是需要求的值。

 

Source Code

 

 1 #include<iostream>
 2 #include<vector>//for map
 3 #include<queue>//for spfa 
 4 using namespace std;
 5 #define MAXN 50010
 6 #define pb push_back 
 7 int dis[MAXN],used[MAXN];
 8 int aa=INT_MAX,bb=-1;//aa最小bb最大 
 9 struct edge
10 {
11     int p;
12     int len;
13 }tmp;
14 vector<edge>map[MAXN];
15 
16 void spfa()
17 {
18     int i,t;
19     queue<int>Q;
20     for(i=aa;i<=bb;i++)
21         dis[i]=-INT_MAX;
22     dis[aa]=0;
23     used[aa]=1;//先进一个
24     Q.push(aa);
25     while(!Q.empty())
26     {
27         t=Q.front();
28         Q.pop();
29         used[t]=0;//出队列过后,还可能再进
30         int nt=map[t].size();
31         for(i=0;i<nt;i++)
32         {
33             if(dis[map[t][i].p]<dis[t]+map[t][i].len)//求最长路
34             {
35                 dis[map[t][i].p]=dis[t]+map[t][i].len;
36                  if(!used[map[t][i].p])
37                  {
38                       used[map[t][i].p]=1;
39                       Q.push(map[t][i].p);
40                  }
41             }
42            }
43     }
44 }
45 int main()
46 {
47     int i,n;
48     scanf("%d",&n);
49     int u,v,w;
50     for(i=1;i<=n;i++)
51     {
52         scanf("%d%d%d",&u,&v,&w);
53         if(u<aa) aa=u;
54         if(v+1>bb) bb=v+1;
55         tmp.len=w;
56         tmp.p=v+1;
57         map[u].pb(tmp);
58     }//添加ci边
59     for(i=aa;i<=bb;i++)
60     {
61         tmp.len=0;
62         tmp.p=i+1;
63         map[i].pb(tmp);
64         tmp.len=-1;
65         tmp.p=i;
66         map[i+1].pb(tmp);
67     }//添加0边和-1边
68     spfa();
69     printf("%d\n",dis[bb]);
70     return 0;
71 }
72 

 

 

技术总结:技术上使用了STL的vector让存储图的邻接表非常方便。spfa的时候省事用了STL的queue。基本的操作就是pop(),push(),front(),size(),empty()


还有一个贪心算法:先按后端点排序,把前面的要求越往后放越好,这样后面放的时候就可以利用前面放的结果。贪心为什么是正确的?

Feedback

# re: POJ 1201 Intervals 差分约束+spfa  回复  更多评论   

2010-08-04 14:28 by Rothschild
不错...感谢...但是有些地方我不是理解不了...

# re: POJ 1201 Intervals 差分约束+spfa  回复  更多评论   

2010-10-16 17:06 by chengouxuan
请问为什么路径长度和所求数字个数有关系

# re: POJ 1201 Intervals 差分约束+spfa  回复  更多评论   

2011-07-31 17:31 by 天青色~~
按你这样建图,跑出来时间花的多,可以求最短路,效率高些

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理