题目大意:给你 n 个区间[ai , bi] (1 <= i <= n) ,和 n 个数ci ,让你找出一个集合 Z, 使得对于所有的i (1 <= i <= n)来说, Z 中的数字 在 区间[ai , bi] 中个数 >= ci ,找出包含元素个数最少的 集合 Z , 并输出其大小 。
解题思路:这是一道差分约束题,设 s[ i ] 表示集合Z中 小于等于 数字 i 的元素个数,则由题意得出如下约束条件:
1、对于所有的[ai , bi] , 有 s[ bi ] - s[ai - 1] >= ci ,变换后得s[ ai - 1 ] - s[bi] <= - ci 。
2、s[ i ] - s[ i - 1 ] >= 0 ,变换后得 s[ i - 1] - s[ i ] <= 0
3 、s[ i ] - s[ i - 1] <= 1 ,变换后得 s[ i - 1 ] - s[ i ] <= -1
根据约束条件建立有向图,以所有 bi 的 最大值 maxn 为源点 , 求出源点到达其他各点的最短路 ,设所有ai 中的最小值 Min ,那么 -1 * dist[ Min - 1 ] 就是所求答案。
请看代码:
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<vector>
#include<queue>
#define mem(a , b) memset(a , b , sizeof(a))
using namespace std ;
const int MAXN = 15e4 + 5 ;
const int INF = 0x7fffffff ;
struct Edge
{
int adj ;
int d ;
int next ;
} e[MAXN] ;
int head[MAXN] ;
int dist[MAXN] ;
bool inq[MAXN] ;
int ecnt ;
int Min , Maxn ;
int n ;
void chu()
{
mem(head , -1) ;
ecnt = 0 ;
}
void init()
{
int i ;
Min = INF ;
Maxn = -1 ;
for(i = 0 ; i < n ; i ++)
{
int a , b , c ;
scanf("%d%d%d" , &a , &b , &c) ;
a ++ ;
b ++ ;
if(Min > a) Min = a ;
if(Maxn < b) Maxn = b ;
c *= (-1) ;
e[ecnt].adj = a - 1 ;
e[ecnt].d = c ;
e[ecnt].next = head[b] ;
head[b] = ecnt ;
ecnt ++ ;
}
for(i = Min ; i <= Maxn ; i ++)
{
e[ecnt].adj = i ;
e[ecnt].d = 1 ;
e[ecnt].next = head[i - 1] ;
head[i - 1] = ecnt ;
ecnt ++ ;
e[ecnt].adj = i - 1 ;
e[ecnt].d = 0 ;
e[ecnt].next = head[i] ;
head[i] = ecnt ;
ecnt ++ ;
}
}
queue<int> q ;
void spfa(int u)
{
mem(inq , 0) ;
while (!q.empty()) q.pop() ;
q.push(u) ;
inq[u] = 1 ;
int tmp ;
while (!q.empty())
{
tmp = q.front() ;
q.pop() ;
inq[tmp] = 0 ;
int i ;
for(i = head[tmp] ; i != -1 ; i = e[i].next)
{
int v = e[i].adj ;
int td = e[i].d ;
if(dist[tmp] != INF && dist[tmp] + td < dist[v])
{
dist[v] = dist[tmp] + td ;
if(!inq[v])
{
q.push(v) ;
inq[v] = 1 ;
}
}
}
}
}
void solve()
{
int i ;
for(i = Min - 1 ; i <= Maxn ; i ++)
{
dist[i] = 0 ;
}
dist[Maxn] = 0 ;
spfa(Maxn) ;
printf("%d\n" , -1 * dist[Min - 1]) ;
}
int main()
{
while (scanf("%d" , &n) != EOF)
{
chu() ;
init() ;
solve() ;
}
return 0 ;
}