cogs #743


題目鏈接


最大費用最大流


如何構圖?

設源點爲 S ,匯點爲 T

將所有的端點離散化,

S 點向第一個點連邊,每個點向下一個點連邊,最後一個點向 T 點連邊,流量都爲 k ,費用都爲 0

對於每條線段,從左端點向右端點連邊,流量爲 1 ,費用爲其長度。

這樣就限制了選擇的線段數量,同時使得總長度最大。


#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <string>
#include <map>
#include <vector>
#include <stack>
#include <queue>
#include <utility>
#include <iostream>
#include <algorithm>

template<class Num>void read(Num &x)
{
    char c; int flag = 1;
    while((c = getchar()) < '0' || c > '9')
        if(c == '-') flag *= -1;
    x = c - '0';
    while((c = getchar()) >= '0' && c <= '9')
        x = (x<<3) + (x<<1) + (c-'0');
    x *= flag;
    return;
}
template<class Num>void write(Num x)
{
    if(x < 0) putchar('-'), x = -x;
    static char s[20];int sl = 0;
    while(x) s[sl++] = x%10 + '0',x /= 10;
    if(!sl) {putchar('0');return;}
    while(sl) putchar(s[--sl]);
}
#define REP(__i,__start,__end) for(int __i = (__start); __i <= (__end); __i++)

const int maxn = 510, node = maxn << 1, edgenum = node << 2, INF = 0x3f3f3f3f;

int n, _k;

struct Edge
{
    int v, cap, cost, next;

    Edge(int v = 0,int cap = 0,int cost = 0,int next = 0):v(v), cap(cap), cost(cost), next(next){}

}edge[edgenum];

#define St first
#define Ed second
std::pair<int, int> seg[maxn];
int bowl[node], bsize;
int head[node], el = 1, S, T, ind;

int dist[node], fr[node], fd[node];

void newedge(int u,int v,int cap,int cost)
{
    edge[++el] = Edge(v, cap, cost, head[u]), head[u] = el;
    edge[++el] = Edge(u, 0, -cost, head[v]), head[v] = el;
}

bool SPFA()
{
    static int line[node];
    static bool hash[node];
    int f = 0, r = 0;

    REP(i, 1, ind) dist[i] = -INF, fr[i] = fd[i] = 0;

    dist[S] = 0, line[r] = S, r = (r + 1)%node;
    hash[S] = true;

    while(f != r)
    {
        int x = line[f], p, calc;
        line[f] = 0, f = (f + 1)%node;
        hash[x] = false;

        for(int i = head[x]; i; i = edge[i].next)
            if(edge[i].cap)
            {
                p = edge[i].v, calc = dist[x] + edge[i].cost;

                if(calc > dist[p])
                {
                    dist[p] = calc, fr[p] = x, fd[p] = i;

                    if(!hash[p])
                    {
                        if(dist[p] <= dist[line[f]])
                            f = (f - 1 + node)%node, line[f] = p;
                        else
                            line[r] = p, r = (r + 1)%node;

                        hash[p] = true;
                    }
                }
            }
    }

    return (dist[T] > -INF);
}

int change(int a,int flow)
{
    if(a != S)
    {
        flow = std::min(flow, edge[fd[a]].cap);
        flow = change(fr[a], flow);

        edge[fd[a]].cap -= flow;
        edge[fd[a]^1].cap += flow;
    }

    return flow;
}

void init()
{
    int u, v;

    read(n), read(_k);

    REP(i, 1, n)
    {
        read(u), read(v);
        seg[i] = std::make_pair(u, v);
    }
}
void prework()
{
    REP(i, 1, n)
    {
        bowl[i<<1] = seg[i].St;
        bowl[(i<<1) - 1] = seg[i].Ed;
    }

    std::sort(bowl + 1, bowl + (n << 1) + 1);
    bsize = std::unique(bowl + 1, bowl + (n << 1) + 1) - (bowl + 1);

    S = bsize + 1, T = bsize + 2, ind = T;

    REP(i, 1, bsize - 1) newedge(i, i + 1, INF, 0);
    newedge(S, 1, _k, 0), newedge(bsize, T, _k, 0);

    REP(i, 1, n)
    {
        int len = seg[i].Ed - seg[i].St;
        seg[i].St = std::lower_bound(bowl + 1, bowl + bsize + 1, seg[i].St) - bowl;
        seg[i].Ed = std::lower_bound(bowl + 1, bowl + bsize + 1, seg[i].Ed) - bowl;
        newedge(seg[i].St, seg[i].Ed, 1, len);
    }

}
int solve()
{
    int maxcost = 0, maxflow = 0;

    while(SPFA())
    {
        maxcost += dist[T];
        maxflow += change(T, INF);
    }

    return maxcost;
}

int main()
{
    freopen("interv.in","r",stdin);
    freopen("interv.out","w",stdout);

    init(), prework(), write(solve());

    fclose(stdin);
    fclose(stdout);
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章