ZOJ--1508(差分约束)
2015-01-06 16:59:05
思路:HDU/POJ上都有这题。
启蒙题。文库这篇文章讲得不错。
总的来说就是利用最短/长路中的距离三角不等式来建图。
S(i)表示1-i中在Z集合中的个数,那么首先有基本约束:1 >= S(i) - S(i -1) >= 0,再根据题目的输入:S(b) - S(a - 1) >= c
把S(i) - S(j) >= k中的S(i)看做点dis(i),k看做边权,那么式子转化为:dis(i) - dis(j) >= k --> dis(i) >= dis(j) + k,其实就表示从 j 到 i 点有一条权为k的边,因为dis表示起点到某点的最长距离,所以上述不等式自然成立。那么我们就建边(j,i),权为k。
跑一遍最长路的spfa,这样就能得到不等式组的解,这个解实际上是使得dis(i) - dis(j) >= k尽量向等号发展,其实就是得到S(i) - S(j)的最小值解,题目要求最短长度(即S(max) - S(min),min表示最小点标号-1,max表示最大点标号),那么计算出的dis(max)就是答案。
注意:既然就的是最长路,那么dis数组初始化应该为负无穷。
1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <cmath> 5 #include <vector> 6 #include <map> 7 #include <set> 8 #include <stack> 9 #include <queue> 10 #include <iostream> 11 #include <algorithm> 12 using namespace std; 13 #define lp (p << 1) 14 #define rp (p << 1|1) 15 #define getmid(l,r) (l + (r - l) / 2) 16 #define MP(a,b) make_pair(a,b) 17 typedef long long ll; 18 typedef unsigned long long ull; 19 typedef pair<int,int> pii; 20 const int INF = (1 << 30) - 1; 21 const int maxn = 50010; 22 23 int N,tmax,tmin; 24 int first[maxn],ecnt; 25 int inq[maxn],dis[maxn]; 26 27 struct edge{ 28 int v,next,cost; 29 }e[3 * maxn]; 30 31 void Add_edge(int u,int v,int c){ 32 e[++ecnt].next = first[u]; 33 e[ecnt].v = v; 34 e[ecnt].cost = c; 35 first[u] = ecnt; 36 } 37 38 void Spfa(int s){ 39 queue<int> Q; 40 memset(inq,0,sizeof(inq)); 41 for(int i = tmin; i <= tmax; ++i) dis[i] = -INF; 42 inq[s] = 1; 43 dis[s] = 0; 44 Q.push(s); 45 while(!Q.empty()){ 46 int x = Q.front(); Q.pop(); 47 inq[x] = 0; 48 for(int i = first[x]; i != -1; i = e[i].next){ 49 int v = e[i].v; 50 if(dis[v] < dis[x] + e[i].cost){ 51 dis[v] = dis[x] + e[i].cost; 52 if(inq[v] == 0){ 53 inq[v] = 1; 54 Q.push(v); 55 } 56 } 57 } 58 } 59 } 60 61 int main(){ 62 int a,b,c; 63 while(scanf("%d",&N) != EOF){ 64 memset(first,-1,sizeof(first)); 65 ecnt = tmax = 0; 66 tmin = INF; 67 for(int i = 1; i <= N; ++i){ 68 scanf("%d%d%d",&a,&b,&c); 69 a++; 70 b++; 71 //S(b) - S(a-1) >= c 72 //S(b) >= S(a - 1) + c 73 Add_edge(a - 1,b,c); 74 tmax = max(tmax,b); 75 tmin = min(tmin,a - 1); 76 } 77 //S(i) - S(i - 1) >= 0 78 //S(i) - S(i - 1) <= 1 --> S(i - 1) - S(i) >= -1 79 for(int i = tmin + 1; i <= tmax; ++i){ 80 Add_edge(i - 1,i,0); 81 Add_edge(i,i - 1,-1); 82 } 83 Spfa(tmin); 84 printf("%d\n",dis[tmax]); 85 } 86 return 0; 87 } 88