给你一个集合,然后有如下输入,a ,b ,c表示在范围[a,b]里面有至少有c个元素,最后问你整个集合最少多少个元素。
思路:
和HDU1384一模一样,首先这个题目可以用差分约束来解决,是大于等于所以跑最长路(如果非要跑最短路建-权也可以),说下建图,首先我们把每个区间抽象出来,区间的两个端点之间的元素个数 [a ,b] = c 可以抽象成 点a,和点(b + 1)之间的距离 大于等于c,那么这样就可以把输入建进去了,还有个关键的地方就是题目的隐含条件,一般的查分约束的关键都是在于找隐含条件,这个题目的隐含条件就是相邻的
两个点的元素个数 >= 0 && <= 1,其他的没啥了。
#include<stdio.h>
#include<string.h>
#include<queue>
#define N_node 55000
#define N_edge 210000
#define INF 100000000000000
using namespace std;
typedef struct
{
int to ,next;
__int64 cost;
}STAR;
STAR E[N_edge];
int list[N_node] ,tot;
__int64 s_x[N_node];
void add(int a ,int b ,__int64 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;
int mark[N_node] = {0};
int in[N_node] = {0};
s_x[s] = 0;
mark[s] = in[s] = 1;
queue<int>q;
q.push(s);
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;
q.push(xin);
if(++in[xin] > n) return 0;
}
}
}
}
return 1;
}
int maxx(int x ,int y)
{
return x > y ? x : y;
}
int minn(int x ,int y)
{
return x < y ? x : y;
}
int main ()
{
int n ,a ,b ,i;
__int64 c;
while(~scanf("%d" ,&n))
{
memset(list ,0 ,sizeof(list));
tot = 1;
int Max = 0 ,Min = 100000000;
for(i = 1 ;i <= n ;i ++)
{
scanf("%d %d %I64d" ,&a ,&b ,&c);
b ++;
add(a ,b ,c);
Max = maxx(Max ,b);
Min = minn(Min ,a);
}
for(i = Min ;i <= Max ;i ++)
{
add(i - 1 ,i ,0);
add(i ,i - 1 ,-1);
}
spfa(Min ,Max);
printf("%I64d
" ,s_x[Max]);
}
return 0;
}