POJ 1201 Intervals(差分约束系统)

题意:求一个包含元素最少集合Z,满足以下条件

给定区间[ai, bi]使得Z里面有 >= ci 个元素在区间[ai, bi]里面,求最少的元素个数


思路:

设 s[i]:集合Z里面 <= i的元素个数,那么由题意:s[ai] - s[bi] >= ci ,这是差分约束系统,光是这个建立不了通路,所以还有 0 <= s[i] - s[i - 1] <= 1,这样就建立起来了,由于一定有解,故不存在负环


#include
#include
#include
#include
#include
#include
#define bug printf("CCCCC\n")
const int maxn = 5 * 1e4 + 10;
const int INF = 1e9;
using namespace std;

struct P {
    int to, cost;
    P(int t, int c) : to(t), cost(c) {}
};
int d[maxn], vis[maxn], cnt[maxn];
int n, a, b, c, l, r;
vector

G[maxn]; bool operator < (P p, P q) { return p.cost > q.cost; } void init() { fill(d, d + maxn, INF); memset(vis, 0, sizeof(vis)); memset(cnt, 0, sizeof(cnt)); for(int i = 0; i < maxn; i++) G[i].clear(); l = INF; r = -1; } bool spfa(int from, int to) { vis[from] = 1; d[from] = 0; queue q; q.push(from); while(!q.empty()) { int u = q.front(); q.pop(); vis[u] = 0; for(int i = 0; i < G[u].size(); i++) { int v = G[u][i].to; if(d[v] > d[u] + G[u][i].cost) { d[v] = d[u] + G[u][i].cost; if(vis[v]) continue; vis[v] = 1; q.push(v); if(++cnt[v] > n) return true; } } } return false; } int main() { while(scanf("%d", &n) != EOF) { init(); for(int i = 0; i < n; i++) { scanf("%d %d %d", &a, &b, &c); a++; b++; G[b].push_back(P(a - 1, -c)); l = min(l, a); r = max(r, b); } for(int i = l; i <= r; i++) { G[i - 1].push_back(P(i, 1)); G[i].push_back(P(i - 1, 0)); } spfa(r, l - 1); int mind = d[l - 1]; printf("%d\n", -mind); } return 0; }



你可能感兴趣的:(数据结构)