标签:
Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 24948 | Accepted: 9491 |
Description
Input
Output
Sample Input
5 3 7 3 8 10 3 6 8 1 1 3 1 10 11 1
Sample Output
6
Source
差分约束的区间约束问题。
题意:给定n(n <= 50000)个整点闭区间和这个区间中至少有多少整点需要被选中,每个区间的范围为[ai, bi],并且至少有ci个点需要被选中,其中0 <= ai <= bi <= 50000,问[0, 50000]至少需要有多少点被选中。
题解:这个题的话是典型的差分约束问题,s[i]代表 [0,i]区间内有多少被选中,所以d[i] - d[j-1] >= w ,但是由于 j是从 0 开始,所以下标要+1,还有就是对于某个区间 [i,i],0<=s[i+1]-s[i]<=1,这样的话根据约束条件就可以求出s->t的最长路即是最后的结果。
差分约束不等式的标准化:
如果给出的不等式有"<="也有">=",又该如何解决呢?很明显,首先需要关注最后的问题是什么,如果需要求的是两个变量差的最大值,那么需 要将所有不等式转变成"<="的形式,建图后求最短路;相反,如果需要求的是两个变量差的最小值,那么需要将所有不等式转化成">=",建图 后求最长路。
#include <iostream> #include <cstdio> #include <string.h> #include <queue> #include <algorithm> #include <math.h> using namespace std; typedef long long LL; const int INF = 999999999; const int N = 160000; const int M = 50005; int n; struct Edge{ int v,w,next; }edge[N]; int head[M]; int tot; void init(){ memset(head,-1,sizeof(head)); tot = 0; } void addEdge(int u,int v,int w,int &k){ edge[k].v = v,edge[k].w = w,edge[k].next = head[u],head[u] = k++; } bool vis[M]; int low[M]; int spfa(int s,int t){ for(int i=s;i<=t;i++){ vis[i] = false; low[i] = -INF; ///求最长路初始值应该是 -INF } queue<int> q; low[s] = 0; q.push(s); while(!q.empty()){ int u = q.front(); q.pop(); vis[u] = false; for(int k=head[u];k!=-1;k=edge[k].next){ int v = edge[k].v,w = edge[k].w; if(low[v]<low[u]+w){ low[v] = low[u]+w; if(!vis[v]){ vis[v] = true; q.push(v); } } } } return low[t]-low[s]; } int main(){ while(scanf("%d",&n)!=EOF){ init(); int MIN = INF,MAX = -1; for(int i=1;i<=n;i++){ int u,v,w; scanf("%d%d%d",&u,&v,&w); MAX = max(MAX,v+1); MIN = min(MIN,u); addEdge(u,v+1,w,tot); } // printf("%d %d\n",MIN,MAX); for(int i=MIN;i<MAX;i++){ addEdge(i,i+1,0,tot); addEdge(i+1,i,-1,tot); } printf("%d\n",spfa(MIN,MAX)); } return 0; }
标签:
原文地址:http://www.cnblogs.com/liyinggang/p/5695818.html