You are given n closed, integer intervals [ai, bi] and n integers c1, ..., cn.
Write a program that:
> reads the number of intervals, their endpoints and integers c1, ..., cn from the standard input,
> computes the minimal size of a set Z of integers which has at least ci common elements with interval [ai, bi], for each i = 1, 2, ..., n,
> writes the answer to the standard output.
Input
The first line of the input contains an integer n (1 <= n <= 50 000) - the number of intervals. The following n lines describe the intervals. The i+1-th line of the input contains three integers ai, bi and ci separated by single spaces and such that 0 <= ai <= bi <= 50 000 and 1 <= ci <= bi - ai + 1.
Process to the end of file.
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
3 7 3
8 10 3
6 8 1
1 3 1
10 11 1
Sample Output
6
一个上午才略微整明白了差分约束是什么鬼,你暑假干什么去了??
首先他运用的模型是某两个点之间大小的不等式,那我们可以把这个式子转化成图上的距离求最短路。但是,这是一个隔路的东西:如果是两点之差>=定值,我们求最长路;两点之差<=定值,求最短路。注意建边的方式不要搞反。by the way感觉差分约束的建图是图论里面最简单的,与2-sat和网络流相比~~
再说这个题:
有一个序列,题目用n个整数组合 [ai,bi,ci]来描述它,[ai,bi,ci]表示在该序列中处于[ai,bi]这个区间的整数至少有ci个。如果存在这样的序列,请求出满足题目要求的最短的序列长度是多少。如果不存在则输出 -1。
那么很容易想到把区间上的点抽象成图上的点,转而表示成两点之差>=定值的建图,需要注意不要误解论文,是从左到右连边而不是从右向左连边!还有,我们加边加的点只是1-5000中的一段,所以你怎么可以输出dist[n]呢?这是没理解好本质啊!一边建边一边更新现有区间的最右端点和最左端点,对于我们来说有用的只有这一段。为什么必须这么算?少的为什么影响结果?看论文这句话:这里面多了一个序号为0的端点,这个端点是干嘛的?是源点啊!所以不可以那么建图
特别重要的一点:清零!
/******************** zoj1508 2016.3.2 5572 120 C++ (g++ 4.7.2) ********************/ #include <iostream> #include<cstdio> #include<cstring> #include<vector> #include<queue> using namespace std; const int inf=0x3f3f3f3f; const int maxn=50005; struct Edge { int v,cost; Edge(int _v=0,int _cost=0):v(_v),cost(_cost){} }; vector<Edge>E[maxn]; void addedge(int u,int v,int w) { E[u].push_back(Edge(v,w)); } bool vis[maxn]; int cnt[maxn]; int dist[maxn]; bool spfa(int start,int n) { memset(vis,false,sizeof(vis)); memset(dist,-inf,sizeof(dist)); vis[start]=true; dist[start]=0; queue<int>que; while(!que.empty()) que.pop(); que.push(start); memset(cnt,0,sizeof(cnt)); cnt[start]=1; while(!que.empty()) { int u=que.front(); que.pop(); vis[u]=false; for(int i=0;i<E[u].size();i++) { int v=E[u][i].v; if(dist[v]<dist[u]+E[u][i].cost) { dist[v]=dist[u]+E[u][i].cost; if(!vis[v]) { vis[v]=true; que.push(v); if(++cnt[v]>n) return false; } } } } return true; } int main() { // freopen("cin.txt","r",stdin); int n,left=maxn,right=1; while(~scanf("%d",&n)) { int a,b,c; for(int i=0;i<=n;i++) E[i].clear(); for(int i=1;i<=n;i++) { scanf("%d%d%d",&a,&b,&c); if(left>a+1) left=a+1; if(right<b+1) right=b+1; addedge(a,b+1,c); } for(int i=left;i<=right;i++) { addedge(i-1,i,0); addedge(i,i-1,-1); } spfa(left-1,right-left+2); printf("%d\n",dist[right]); for(int i=left-1;i<=right;i++) E[i].clear();//!!!! } return 0; }