标签:
writes the answer to the standard output.
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
Sample Output
6
Source
Southwestern Europe 2002
题目大意:给你N个整数点构成的区间[ai,bi](ai,bi都为整数),在区间[ai,bi]上最少选ci个点。
ci可在区间[ai,bi]中随意取,但是不能重复。问:要满足在N个区间取点,至少要选多少个点。
思路:差分约束思想。设Si为前i项的整数个数,则S(bi) - S(ai-1) >= ci。还有两个隐含约束条件
S(i-1) - S(i) <= 0,S(i)-S(i-1) <= 1。把这三种约束构建一个差分约束系统,用SPFA求最短路径。
#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #include<queue> using namespace std; const int MAXN = 50050; const int INF = 0xffffff0; struct EdgeNode { int to; int w; int next; }Edges[MAXN << 2]; int Head[MAXN],Dist[MAXN],vis[MAXN]; int SPFA(int Left,int Right) { for(int i = Left; i <= Right+1; ++i) Dist[i] = INF; memset(vis,0,sizeof(vis)); queue<int> Q; Q.push(Right); vis[Right] = 1; Dist[Right] = 0; while( !Q.empty() ) { int u = Q.front(); Q.pop(); vis[u] = 0; for(int i = Head[u]; i != -1; i = Edges[i].next) { int temp = Dist[u] + Edges[i].w; if( temp < Dist[Edges[i].to]) { Dist[Edges[i].to] = temp; if( !vis[Edges[i].to] ) { vis[Edges[i].to] = 1; Q.push(Edges[i].to); } } } } return -Dist[Left]; } int main() { int N,Left,Right,a,b,c; while(~scanf("%d",&N)) { Left = MAXN,Right = 0; memset(Head,-1,sizeof(Head)); memset(Edges,0,sizeof(Edges)); int id = 0; for(int i = 0; i < N; ++i) { scanf("%d%d%d",&a,&b,&c); Edges[id].to = a; Edges[id].w = -c; Edges[id].next = Head[b+1]; Head[b+1] = id++; if(a < Left) Left = a; if(b > Right) Right = b; } Right++; for(int i = Left; i < Right; ++i) { Edges[id].to = i; Edges[id].w = 0; Edges[id].next = Head[i+1]; Head[i+1] = id++; Edges[id].to = i+1; Edges[id].w = 1; Edges[id].next = Head[i]; Head[i] = id++; } printf("%d\n",SPFA(Left,Right)); } return 0; }
标签:
原文地址:http://blog.csdn.net/lianai911/article/details/43168263