码迷,mamicode.com
首页 > 其他好文 > 详细

POJ 3469 最小割定理

时间:2015-06-07 13:46:41      阅读:78      评论:0      收藏:0      [点我收藏+]

标签:

其实就是搬砖

有N个任务,一台双核电脑

每个任务可以在任意且仅一个核上运行

每个在核A上花费Ai,核B上花费Bi

有M对关系,若任务x与任务y不在一个核上运行,则要花费Cx,y

求一种安排任务的方式,使得总花费最小

解法:最小割

源点向每个任务连边,容量Ai

每个任务向汇点连边,容量Bi

对于每一对关系x,y Cx,y:在x与y之间连双向边,容量Cx,y

最小割即为所求

每个任务与S割开表示在A上完成,与T割开表示在B上完成

对于每一对关系x,y Cx,y

若同时在A完成,割开S与x,y之间的边,花费Ax+Ay

若同时在B完成,割开T与x,y之间的边,花费Bx+By

若x在A完成,y在B完成,则割开x,y之间的边,花费Ax+By+Cx,y

技术分享
若x在B完成,y在A完成,则割开x,y之间的边,花费Bx+Ay+Cx,y
纯属搬砖
代码:
#include <set>
#include <map>
#include <queue>
#include <deque>
#include <cmath>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cassert>
#include <iostream>
#include <algorithm>

#define dprint(expr) fprintf(stderr, #expr " = %d\n", expr)

using namespace std;

typedef long long LL;
typedef pair <int, int> PII;

const int N = 2e4 + 7;
const int M = 1e6 + 7;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const double EPS = 1e-6;
const double PI = acos(-1.0);

struct edge
{
    int x, ne, c, f;
};

struct NetFlow
{
    edge e[M];
    int head[N], h[N], dis[N], q[N], stack[N];
    bool used[N];
    int pos, stop, top, S, T;
    LL flow;
    
    void init(int s, int t)
    {
        pos = 1;
        flow = top = 0;
        S = s;
        T = t;
        memset(head, 0, sizeof(head));
    }
    
    void adde(int u, int v, int c)
    {
        e[++pos] = (edge){v, head[u], c, 0};
        head[u] = pos;
        e[++pos] = (edge){u, head[v], c, c};
        head[v] = pos;
    }
    
    bool number()
    {
        memset(dis, 0, sizeof(dis));
        memset(used, 0, sizeof(used));
        int p1, p2, x;
        used[q[p1 = p2 = 1] = S] = true;
        while (p1 <= p2)
        {
            x = q[p1++];
            for (int i = head[x]; i; i = e[i].ne)
                if (e[i].c > e[i].f && !used[e[i].x])
                {
                    used[q[++p2] = e[i].x] = true;
                    dis[e[i].x] = dis[x] + 1;
                }
        }
        if (!used[T])
            return false;
        memcpy(h, head, sizeof(head));
        return true;
    }
    
    bool dinic(int x)
    {
        if (x == T)
        {
            int cut = INF;
            for (int i = 1; i <= top; ++i)
                cut = min(cut, e[stack[i]].c - e[stack[i]].f);
            for (int i = 1; i <= top; ++i)
            {
                e[stack[i]].f += cut;
                e[stack[i] ^ 1].f -= cut;
                if (e[stack[i]].c == e[stack[i]].f)
                    stop = i;
            }
            flow += cut;
            return true;
        }
        for (int &i = h[x]; i; i = e[i].ne)
            if (e[i].c > e[i].f && dis[x] == dis[e[i].x] - 1)
            {
                stack[++top] = i;
                if (dinic(e[i].x) && stop != top)
                {
                    --top;
                    return true;
                }
                --top;
            }
        return false;
    }
    
    LL maxflow()
    {
        while (number())
            dinic(S);
        return flow;
    }
}net;

int main(void){
    int n, m;
    while (scanf("%d%d", &n, &m) == 2) {
        int S = n + 1, T = n + 2;
        net.init(S, T);
        for (int i = 1; i <= n; ++i) {
            int a, b;
            scanf("%d%d", &a, &b);
            net.adde(S, i, a);
            net.adde(i, T, b);
        }
        for (int i = 1; i <= m; ++i) {
            int u, v, w;
            scanf("%d%d%d", &u, &v, &w);
            net.adde(u, v, w);
            net.adde(v, u, w);
        }
        int ans = net.maxflow();
        printf("%d\n", ans);
    }

    return 0;
}

 

POJ 3469 最小割定理

标签:

原文地址:http://www.cnblogs.com/addf/p/4558359.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!