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         

 

posted @ 2015-01-06 17:07  Naturain  阅读(137)  评论(0编辑  收藏  举报