POJ Intervals (最小费用最大流)

来源:互联网 发布:办公室网络安装 编辑:程序博客网 时间:2024/05/18 03:14

题目: LINK

给定 N 个带权的开区间,第 i 个区间覆盖(ai, bi),权为 wi。现在要你挑出一些区间使得总权值最大,并且满足实轴上任意一个点被覆盖不超过 K 次。(1 <= K <= N <= 200, 1 <= ai < bi <= 100,000, 1 <= wi <= 100,000)

首先要将每个区间的端点离散化,1..M,另加源 s=0,汇 t=M+1;对每个点 i (0 <= i <= M)加边(i, i+1, K, 0);
对每个区间(ai, bi)加边(ai’, bi’, 1, -wi),其中ai’, bi’分别表示 ai, bi 离散化后对应的数值
按照这个图求最小费用最大流,得到的最小费用的相反数就是要求的结果.

#include <cstdio>#include <cstring>#include <algorithm>#include <iostream>#include <string>#include <vector>#include <cmath>#include <queue>#include <map>#include <set>using namespace std; #define INF 1000000000//typedef __int64 LL; #define N 444int t, n, k , tot, hh[N], dis[N], inq[N], S, T, pre[N]; set<int> se; map<int, int> ma; struct node {    int u, v, w, c, next; }edge[1000000]; struct no {    int u, v, w; }ee[N]; void init() {    memset(hh, -1, sizeof(hh));     tot = 0; }void add(int u, int v, int w, int c) {    edge[tot].u = u; edge[tot].v = v;     edge[tot].w = w; edge[tot].c = c;     edge[tot].next = hh[u]; hh[u] = tot ++; }int spfa() {    queue<int > Q;     memset(pre, -1, sizeof(pre));     memset(inq, 0, sizeof(inq));     for(int i = 0; i <= T; i++) dis[i] = INF; // ?    dis[S] = 0; inq[S] = 1;     Q.push(S);     while(!Q.empty()) {        int u = Q.front(); Q.pop();         inq[u] = 0;         for(int i = hh[u]; i != -1; i = edge[i].next) {            int v = edge[i].v;             if(edge[i].w && dis[v] > dis[u] + edge[i].c){                pre[v] = i; dis[v] = dis[u] + edge[i].c;                 if(!inq[v]) {                    inq[v] = 1; Q.push(v);                 }            }        }    }    return dis[T] != INF; }int mcml() {    int flow, cost;     flow = cost = 0;     while(spfa()) {        int tmp = INF;         for(int i = pre[T]; i != -1; i = pre[edge[i].u])            tmp = min(tmp, edge[i].w);         flow += tmp;         cost += dis[T] * tmp;         for(int i = pre[T]; i != -1; i = pre[edge[i].u] )            edge[i].w -= tmp, edge[i^1].w += tmp;     }    return cost; }int main() {#ifndef ONLINE_JUDGE    freopen("in.txt", "r", stdin); #endif // ONLINE_JUDGE    scanf("%d", &t);     while(t -- ) {        scanf("%d%d", &n, &k);         init();         se.clear();         ma.clear();         for(int i = 1; i <= n; i++) {            scanf("%d%d%d", &ee[i].u, &ee[i].v, &ee[i].w);             se.insert(ee[i].u); se.insert(ee[i].v);         }        int id = 1;         for(set<int >::iterator it = se.begin(); it != se.end(); it ++) {            ma[*it] = id++;         }        // build map        S = 0; T = id;         for(int i = 0; i < T; i++) {            add(i, i+1, k, 0); add(i+1, i, 0, 0);         }        for(int i = 1; i <= n; i++) {            int id1= ma[ee[i].u];             int id2 = ma[ee[i].v];             add(id1, id2, 1, -ee[i].w); add(id2, id1, 0, ee[i].w);         }        // finish build.        int ans = mcml();         printf("%d\n", -ans);     }    return 0; }


0 0