最小割

一个图,每条边都有一个代价,现在需要破坏一些边使图中的某两个点不连通,求最小的代价是多少。
根据最大流-最小割定理,最小割可以通过最大流来求。
最小割的模板同最大流 如果只要求割成两部分,并不在意隔开了哪些点,这是全图最小割问题,可以供SW算法,模板如下:

HDU 3691 Nubulsa Expo

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define mem(a) memset(a, 0, sizeof(a))

const int maxv = 500;
const int inf = 0x3f3f3f3f;

int v[maxv], d[maxv];
int G[maxv][maxv];
bool vis[maxv];

int Stoer_Wanger(int n) {
    int res = inf;
    for (int i = 1; i <= n; i++) v[i] = i;

    while (n > 1) {
        int k = 1, pre = 1;
        mem(vis); mem(d);
        for (int i = 2; i <= n; i++) {
            k = -1;
            for (int j = 2; j <= n; j++) {
                if ( !vis[ v[j] ] ) {
                    d[ v[j] ] += G[ v[pre] ][ v[j] ];
                    if (k == -1 || d[ v[k] ] < d[ v[j] ] ) {
                        k = j;
                    }
                }
            }
            vis[ v[k] ] = true;
            if (i == n) {
                res = min(res, d[ v[k] ]);
                for (int j = 1; j <= n; j++) {
                    G[ v[pre] ][ v[j] ] += G[ v[j] ][ v[k] ];
                    G[ v[j] ][ v[pre] ] += G[ v[j] ][ v[k] ];
                }
                v[ k ] = v[ n-- ];
            }
            pre = k;
        }
    }
    return res;
}

int main() {
    int n, m, s, u, v, w;
    while (scanf("%d%d%d", &n, &m, &s) != EOF && s) {
        mem(G);
        for (int i = 0; i < m; i++) {
            scanf("%d%d%d", &u, &v, &w);
            G[u][v] += w;
            G[v][u] += w;
        }
        printf("%d\n", Stoer_Wanger(n));
    }
    return 0;
}

POJ 3469 Dual Core CPU

有一台电脑配了一个双核的CPU,现在内存中有N个模块,每个模块在每个CPU中运行的耗费已经被估算出来了,设为Ai 和Bi。同时,其中有M对模块需要共享资源,如果他们运行在同一个CPU中,共享数据的耗费可以忽略不计,否则,还需要额外的费用。必须很好的安排这N个模块,使得总耗费最小。

如果将两个CPU分别视为源点和汇点、模块视为顶点,则可以按照以下方式构图: 对于第 i 个模块在每个CPU中的耗费Ai,Bi,从源点向顶点 i 连接一条容量为 w 的弧、从顶点 i 向汇点连接一条容量为Bi的弧;对于a 模块与 b 模块在不同的CPU中运行造成的额外耗费w,从顶点a 向顶点 b连接一条容量为 w 的弧。此时每个顶点(模块)都和源点及汇点(两个CPU)相连,即每个模块都可以在任意一个CPU中运行。

不难发现,对于图中的任意一个割,源点与汇点必不连通。因此每个顶点(模块)都不可能同时和源点及汇点(两个CPU)相连,即每个模块只能在同一个CPU中运行。此时耗费即为割的容量。显然,当割的容量最小时,总耗费最小。故题目转化为求最小割的容量

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int maxn = 100000;
const int maxm = 1000000;
const int inf = 1000000000;

class Dinic {
public :
    struct Node {
        int u, v, f, next;
    }e[maxm];

    int head[maxn], p, lev[maxn], cur[maxn];
    int que[maxm];

    void init() {
        p = 0;
        memset(head, -1, sizeof(head));
    }

    void add(int u, int v, int f) {
        e[p].u = u; e[p].v = v; e[p].f = f; e[p].next = head[u]; head[u] = p++;
        e[p].u = v; e[p].v = u; e[p].f = 0; e[p].next = head[v]; head[v] = p++;
    }

    bool bfs(int s, int t) {
        int u, v, qin = 0, qout = 0;
        memset(lev, 0, sizeof(lev)); lev[s] = 1; que[qin++] = s;
        while(qout != qin) {
            u = que[qout++];
            for(int i = head[u]; i != -1; i = e[i].next) {
                if(e[i].f > 0 && !lev[v = e[i].v]) {
                    lev[v] = lev[u] + 1, que[qin++] = v;
                    if(v == t) return 1;
                }
            }
        }
        return 0;
    }

    int dfs(int s, int t) {
        int i, f, qin, u, k;
        int flow = 0;
        while(bfs(s, t)) {
            memcpy(cur, head, sizeof(head));
            u = s, qin = 0;
            while(1) {
                if(u == t) {
                    for(k = 0, f = inf; k < qin; k++)
                        if(e[que[k]].f < f) f = e[que[i=k]].f;
                    for(k = 0; k < qin; k++)
                        e[que[k]].f -= f, e[que[k]^1].f += f;
                    flow += f, u = e[que[qin = i]].u;
                }
                for(i = cur[u]; cur[u] != -1; i = cur[u] = e[cur[u]].next)
                    if(e[i].f > 0 && lev[u] + 1 == lev[e[i].v]) break;
                if(cur[u] != -1)
                    que[qin++] = cur[u], u = e[cur[u]].v;
                else {
                    if(qin == 0) break;
                    lev[u] = -1, u = e[que[--qin]].u;
                }
            }
        }
        return flow;
    }
}H;

int main() {
    int n, m;
    while (scanf("%d%d", &n, &m) != EOF) {
        int s = 0, t = n+1;
        H.init();
        int cpu1, cpu2;
        for (int i = 1; i <= n; i++) {
            scanf("%d%d", &cpu1, &cpu2);
            H.add(s, i, cpu1);
            H.add(i, t, cpu2);
        }
        int u, v, w;
        for (int i = 0; i < m; i++) {
            scanf("%d%d%d", &u, &v, &w);
            H.add(u, v, w);
            H.add(v, u, w);
        }
        printf("%d\n", H.dfs(s, t));
    }
    return 0;
}

results matching ""

    No results matching ""