poj 3469 Dual Core CPU (最小割最大流)

思路:

考虑把N个模块按照在哪个核上执行分成两个集合

记核A上执行的模块集合为S,而在核B上执行的模块集合为T。

考虑以模块为顶点,并且还有额外的源点s和汇点t的图。我们也记图的s-t割所对应的包含s的顶点集合为S,包含t的集合为T。此时的总花费为sigma(Ai) + sigma(Bi) + Sigma(wi).

所以我们想通过合适的建边使得花费的总和等于割的容量的话,那么求最小费用只求最小割就好了。

考虑sigma(Ai)这是顶点属于S时产生的花费,所以每个模块向t连一条容量Ai的边就可以对应起来

同理sigma(Bi) 也要从s向每一个模块连一条容量为Bi的边。

最后对应的每个可以进行数据交换的模块组合,连一条费用为wi的双向边.

约束:

1<= N <= 20000

1<= M <= 200000


/***********************************************
 * Author: fisty
 * Created Time: 2015-08-17 15:23:53
 * File Name   : poj3469.cpp
 *********************************************** */
#include <iostream>
#include <cstring>
#include <deque>
#include <cmath>
#include <queue>
#include <stack>
#include <list>
#include <map>
#include <set>
#include <string>
#include <vector>
#include <cstdio>
#include <bitset>
#include <algorithm>
using namespace std;
#define Debug(x) cout << #x << " " << x <<endl
#define Memset(x, a) memset(x, a, sizeof(x))
const int INF = 0x3f3f3f3f;
typedef long long LL;
typedef pair<int, int> P;
#define FOR(i, a, b) for(int i = a;i < b; i++)
#define lson l, m, k<<1
#define rson m+1, r, k<<1|1
#define MAX_N 20010
#define MAX_M 200100
struct edge{
    int to,cap, rev;
};   
vector<edge> G[2*MAX_N];
int level[MAX_N];
int iter[MAX_N];

void add_edge(int from, int to, int cap){
    G[from].push_back((edge){to, cap, G[to].size()});
    G[to].push_back((edge){from, 0, G[from].size()-1});
}
void bfs(int s){
    memset(level, -1, sizeof(level));
    queue<int> que;
    level[s] = 0;
    que.push(s);
    while(!que.empty()){
        int v = que.front(); que.pop();
        for(int i = 0;i < G[v].size(); i++){
            edge &e = G[v][i];
            if(e.cap > 0 && level[e.to] < 0){
                level[e.to] = level[v] + 1;
                que.push(e.to);
            }
        }
    }
}
int dfs(int v, int t, int f){
    if(v == t) return f;
    for(int &i = iter[v];i < G[v].size(); i++){
        edge &e = G[v][i];
        if(e.cap > 0 && level[v] < level[e.to]){
            int d = dfs(e.to, t, min(f, e.cap));
            if(d > 0){
                e.cap -= d;
                G[e.to][e.rev].cap += d;
                return d;
            }
        }
    }
    return 0;
}
int max_flow(int s, int t){
    int flow = 0;
    for(;;){
        bfs(s);
        if(level[t] < 0) return flow;
        memset(iter, 0, sizeof(iter));
        int f;
        while((f = dfs(s, t, INF)) > 0){
            flow += f;
        }
    }
}
int N, M;
int A[MAX_N], B[MAX_N];
int a[MAX_M], b[MAX_M], w[MAX_M];
void solve(){
    int s = N, t = s + 1;
    for(int i = 0;i < N; i++){
        add_edge(i, t, A[i]);
        add_edge(s, i, B[i]);
    }
    for(int i = 0;i < M; i++){
        add_edge(a[i]-1, b[i]-1, w[i]);
        add_edge(b[i]-1, a[i]-1, w[i]);
    }
    printf("%d\n", max_flow(s, t));
}
int main() {
    //freopen("in.cpp", "r", stdin);
    //cin.tie(0);
    //ios::sync_with_stdio(false);
    while(~scanf("%d%d", &N, &M)){
        for(int i = 0;i < N; i++){
            scanf("%d%d", &A[i], &B[i]);
        }
        for(int i = 0;i < M; i++){
            scanf("%d%d%d", &a[i], &b[i], &w[i]);
        }
        solve();
    }
    return 0;
}





发布了331 篇原创文章 · 获赞 15 · 访问量 19万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 编程工作室 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览