POJ 1201 Intervals (差分约束系统)

题意

在区间[0,50000]上有一些整点,并且满足n个约束条件:在区间[ui, vi]上至少有ci个整点,问区间[0, 50000]上至少要有几个整点。

思路

差分约束求最小值。把不等式都转换为>=形式,那么显然有x vi >= x ui-1 + ci,那么就在约束图中连一条(ui-1, vi, ci)的边;当然不要忘记隐含的不等式:x i >= x i-1 + 0;   x i-1 >= x i -1. 建完图后SPFA求最长路径即可

代码

  [cpp] #include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <algorithm> #include <string> #include <queue> #include <cstring> #define MID(x,y) ((x+y)/2) #define MEM(a,b) memset(a,b,sizeof(a)) #define REP(i, begin, m)   for (int i = begin; i < begin+m; i ++) using namespace std; const int MAXN = 50005; const int oo = 0x3fffffff; struct Edge{     int to;     int w;     Edge(){}     Edge(int _to, int _w){  to = _to;   w = _w; } }; struct Gragh{     vector <Edge> adj[MAXN];     queue <int> q;     int vn;     int dist[MAXN], inq_num[MAXN];     bool inq[MAXN];     void init(int n){         vn = n;         for (int i = 0; i <= n; i ++)             adj[i].clear();     }     //if xj >= xi + c, add (i, j, c)     void add_edge(int u, int v, int w){         adj[u].push_back(Edge(v, w));     }     //spfa calculate longest path     bool solve(int s, int t){         while(!q.empty())             q.pop();         MEM(inq, false);    MEM(inq_num, 0);    MEM(dist, -1);      //Note : dist shouldn't initially be 0         dist[s] = 0;    inq[s] = true;  inq_num[s] ++;  q.push(s);         while(!q.empty()){             int u = q.front();             q.pop();             inq[u] = false;             for (int i = 0; i < adj[u].size(); i ++){                 int v = adj[u][i].to;                 if (dist[v] < dist[u] + adj[u][i].w){                     dist[v] = dist[u] + adj[u][i].w;                     if (!inq[v]){                         inq[v] = true;                         inq_num[v] ++;                         if (inq_num[v] > vn)                             return false;                         q.push(v);                     }                 }             }         }         if (dist[t] < oo){             return true;         }     } }spfa; struct intervals{     int u, v, w; }inte[MAXN]; int main(){ //freopen("test.in", "r", stdin); //freopen("test.out", "w", stdout);     int n;     while(scanf("%d", &n) != EOF){         int maxn = 0;         REP(i, 1, n){             scanf("%d %d %d", &inte[i].u, &inte[i].v, &inte[i].w);             inte[i].u ++, inte[i].v ++;             maxn = max(maxn, inte[i].v);         }         spfa.init(maxn+1);         REP(i, 1, maxn){             spfa.add_edge(i-1, i, 0);             spfa.add_edge(i, i-1, -1);         }         REP(i, 1, n){             spfa.add_edge(inte[i].u-1, inte[i].v, inte[i].w);         }         if (spfa.solve(0, maxn)){             printf("%d\n", spfa.dist[maxn]);         }     } return 0; } [/cpp]

你可能感兴趣的:(差分约束)