0
点赞
收藏
分享

微信扫一扫

POJ 1716 区间最小点个数

花明 2022-07-27 阅读 87

题意:
     给你n个区间,每个区间最少取两个元素,问你所有区间最少取几个元素(可以满足
每个区间最少两个元素)。


思路:
     这个题目感觉挺巧妙的,之前在杭电上做过这个题目,这个题目可以用查分约束来做
,对于每一个区间a,b我们可以这样 b - a >= 2 那么建图a->b 长度是2,全建完之后不要忘记题目的隐含条件,查分约束中隐含条件很重要,这个题目的隐含条件就是相邻的两个点之间的个数大于等于0,小于等于1,也就是  0 =< i - (i - 1) <= 1,然后拆成两部分,对于i - (i - 1) >= 0  建立 (i - 1)-> i 长度0,对于i - (i - 1) <= 1先转换成 (i - 1) - i >= -1 建立 i -> (i - 1) 长度是-1,然后以最小点为起点一边最长路,在查分约束中要记住,求最小就跑最长路,求最大就跑最短路,其他的没啥。


#include<stdio.h>

#include<string.h>

#include<queue>
#define N_node 11000

#define N_edge 33000

#define INF 1000000000
using namespace std;
typedef struct

{

int to ,next ,cost;

}STAR;
STAR E[N_edge];

int list[N_node] ,tot;

int mark[N_node] ,mki[N_node] ,s_x[N_node];
void add(int a ,int b ,int c)

{

E[++tot].to = b;

E[tot].cost = c;

E[tot].next = list[a];

list[a] = tot;

}
bool spfa(int s ,int n)

{

for(int i = 0 ;i <= n ;i ++)

s_x[i] = -INF ,mark[i] = mki[i] = 0;

queue<int>q;

q.push(s);

s_x[s] = 0 ,mark[s] = mki[s] = 1;

while(!q.empty())

{

int xin ,tou;

tou = q.front();

q.pop();

mark[tou] = 0;

for(int k = list[tou] ;k ;k = E[k].next)

{

xin = E[k].to;

if(s_x[xin] < s_x[tou] + E[k].cost)

{

s_x[xin] = s_x[tou] + E[k].cost;

if(!mark[xin])

{

mark[xin] = 1;

if(++mki[xin] > n) return 0;

q.push(xin);

}

}

}

}

return 1;

}
int main ()

{

int i ,a ,b ,n ,Min ,Max;

while(~scanf("%d" ,&n))

{

Min = INF ,Max = -INF;

memset(list ,0 ,sizeof(list)) ,tot = 1;

for(i = 1 ;i <= n ;i ++)

{

scanf("%d %d" ,&a ,&b);

b++;

if(Min > a) Min = a;

if(Max < b) Max = b;

add(a ,b ,2);

}

for(i = Min ;i <= Max ;i ++)

add(i - 1 ,i ,0) ,add(i ,i - 1 ,-1);

spfa(Min ,Max);

printf("%d\n" ,s_x[Max]);

}

return 0;

}


  



举报

相关推荐

0 条评论