码迷,mamicode.com
首页 > 其他好文 > 详细

POJ 1201 Intervals (差分约束,最短路)

时间:2015-08-01 12:52:32      阅读:170      评论:0      收藏:0      [点我收藏+]

标签:

 

 

 

题意:假设有一个自然数区间[0,50000],要从中挑出一些自然数出来,但是现在不知道整个区间究竟要挑多少个出来,只知道一部分闭区间[a,b]内至少要挑多少个,所知道的有n个闭区间。问至少要挑出多少个?

 

思路:

  对于所给的区间 cnt[b-a]>=k这可以保证了该区间内个数不少于k。但是由于两边都是闭区间,所以要变cnt[b-(a-1)]>=k,表示b到a之间的个数。也就是说,转成式子是b-(a-1)>=k,变换一下为(a-1)-b<=-k,就满足常见的式子b-a<=k啦,可以建边b指向(a-1),权值为-k。

  但是还有没有其他的约束条件呢?如果我们只是这样建图,那很多个点都不会有联系的啊,比如[3,7]>=2和 [5,9]>=4,建边为2->7和4>9,完全不搭边啊!肯定还有其他联系,相邻的两个数字之间是否可以有边?可以的,至少可以满足a-(a-1)>=0吧?表示a只能被选与不被选。还有呢?每个点最多只能被选一次吧?则有a-(a-1)<=1。

  综合3条式子,可以变形得到:

  (1)(a-1)-b<=-k

  (2)(a-1)-a<=0

  (3)a-(a-1)<=1

  都满足了常见的式子。那么可以建边了。这下每两个相邻数字就起码有两条边。

  我们要求的是什么?满足要求的,整个区间所挑的最小个数。从最大数字出发,进行求最短路后,最小的数的那个点通常就会得到一个负权路径和啦,cost[最小]=负值。而cost[最小]取相反数就是答案了。记得开始前要将cost[起点]置为0。大概思路是这样,但是区间是[0,50000],所以0-1时还会出现负数下标,可以将整个区间右移一位变成[1,50001]。

 

 

 

技术分享
 1 //#include <bits/stdc++.h>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <map>
 5 #include <iostream>
 6 #include <deque>
 7 #include <vector>
 8 #define INF 0x7f7f7f7f
 9 #define pii pair<int,int>
10 #define LL unsigned long long
11 using namespace std;
12 const int N=51010;
13 struct node
14 {
15     int from,to,cost;
16     node(){};
17     node(int from,int to,int cost):from(from),to(to),cost(cost){};
18 }edge[N*4];
19 vector<int> vect[N];
20 int edge_cnt;
21 
22 void add_node(int from,int to,int cost)
23 {
24     edge[edge_cnt]=node(from,to,cost);
25     vect[from].push_back(edge_cnt++);
26 }
27 
28 bool inq[N];
29 int cost[N];
30 int spfa(int small,int big)
31 {
32     memset(inq,  0, sizeof(inq));
33     memset(cost, 0x7f, sizeof(cost));
34     cost[big]=0;
35     deque<int> que(1,big);
36 
37     while(!que.empty())
38     {
39         int x=que.front();que.pop_front();
40         inq[x]=0;
41 
42         for(int i=0; i<vect[x].size(); i++)
43         {
44             node e=edge[vect[x][i]];
45             if(cost[e.to]>cost[x]+e.cost)
46             {
47                 cost[e.to]=cost[x]+e.cost;
48                 if(!inq[e.to])
49                 {
50                     inq[e.to]=1;
51                     if(!que.empty() && cost[e.to]<cost[que.front()])    que.push_front(e.to);
52                     else    que.push_back(e.to);
53                 }
54             }
55         }
56     }
57     return -cost[small];
58 }
59 
60 int main()
61 {
62     //freopen("input.txt", "r", stdin);
63     int n, m, a, b, c;
64     while(~scanf("%d",&n))
65     {
66         edge_cnt=0;
67         memset(edge,0,sizeof(edge));
68         for(int i=0; i<N; i++)  vect[i].clear();
69         int small=INF, big=0;
70 
71         for(int i=0; i<n; i++)
72         {
73             scanf("%d%d%d",&a,&b,&c);
74             add_node(b+1,a,-c);   //右移了1位
75 
76             small=min(small, a+1);
77             big=max(big, b+1);
78         }
79         //每两个点之间的
80         for(int i=small; i<=big; i++)
81         {
82             add_node(i-1, i, 1);
83             add_node(i, i-1, 0);
84         }
85         cout<<spfa(small-1, big)<<endl;
86     }
87     return 0;
88 }
AC代码

 

POJ 1201 Intervals (差分约束,最短路)

标签:

原文地址:http://www.cnblogs.com/xcw0754/p/4693889.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!