poj3680 Intervals

来源:互联网 发布:水性木器漆品牌 知乎 编辑:程序博客网 时间:2024/06/06 06:54
先把区间端点离散化为n个点,再添加源点s和汇点t。s向第一个点连边,容量为k,费用为0;第i个点向第i+1个点连边,容量为oo,费用为0;第n个点向t连边,容量为k,费用为0。假如某个区间端点离散成a,b,则由a向b连边,容量为1,费用为-w(w为该区间的权值)。然后对该网络求最小费用最大流~~
#include <iostream>#include <cstring>#include <cstdio>#include <algorithm>#include <queue>#include <map>using namespace std;const int maxn = 444;const int maxm = 1500;const int oo = 1 << 30;int n, k, idx;int source, sink, vn;int dis[maxn], pre[maxn], head[maxn];bool vis[maxn];map<int, int> m;int a[maxn], b[maxn], w[maxn];struct Node{int u;int v;int cap;int cost;int next;}edge[maxm];void addEdge(int u, int v, int cap, int cost){edge[idx].u = u;edge[idx].v = v;edge[idx].cap = cap;edge[idx].cost = cost;edge[idx].next = head[u];head[u] = idx++;edge[idx].u = v;edge[idx].v = u;edge[idx].cap = 0;edge[idx].cost = -cost;edge[idx].next = head[v];head[v] = idx++;}bool spfa(int s, int t, int n){int cur, i, j;memset(vis, false, sizeof(vis));memset(pre, -1, sizeof(pre));for (i = 0; i <= n; ++i) dis[i] = oo;queue<int> Q;dis[s] = 0;vis[s] = true;Q.push(s);while (!Q.empty()){cur = Q.front();Q.pop();vis[cur] = false;for (i = head[cur]; i != -1; i = edge[i].next){j = edge[i].v;if (edge[i].cap > 0 && dis[cur] + edge[i].cost < dis[j]){dis[j] = dis[cur] + edge[i].cost;pre[j] = i;if (!vis[j]){vis[j] = true;Q.push(j);}}}}return dis[t] != oo;}int minCost(int s, int t, int n){int ret = 0, flow = oo;while (spfa(s, t, n)){int i = t;while (pre[i] != -1){flow = min(flow, edge[pre[i]].cap);i = edge[pre[i]].u;}i = t;while (pre[i] != -1){ret += edge[pre[i]].cost * flow;edge[pre[i]].cap -= flow;edge[pre[i]^1].cap += flow;i = edge[pre[i]].u;}}return ret;}int main(){    int t, cnt, p[maxn];    scanf("%d", &t);    while (t--)    {        idx = 0;        cnt = 0;        memset(head, -1, sizeof(head));        scanf("%d %d", &n, &k);        for (int i = 1; i <= n; ++i)        {            scanf("%d %d %d", &a[i], &b[i], &w[i]);            p[++cnt] = a[i];            p[++cnt] = b[i];        }        sort(p + 1, p + cnt + 1);        int tot = 0;        p[++tot] = p[1];        for (int i = 2; i <= cnt; ++i)        {            if (p[i] != p[tot])                p[++tot] = p[i];        }        for (int i = 1; i <= tot; ++i)        {            m[p[i]] = i;        }        addEdge(0, 1, k, 0);        addEdge(tot, tot + 1, k, 0);        for (int i = 1; i < tot; ++i)            addEdge(i, i + 1, oo, 0);        for (int i = 1; i <= n; ++i)        addEdge(m[a[i]], m[b[i]], 1, -w[i]);        printf("%d\n", -minCost(0, tot + 1, tot + 2));    }    return 0;}