poj3469(*最小割模型)

来源:互联网 发布:淘宝五张宝贝主图规律 编辑:程序博客网 时间:2024/05/19 06:38
/*translation:    要在核A与核B组成的双核cpu上面运行n个模块,给出每个模块在核A、核B上运行的时间。除此之外,接下来还有m组需要交换数据的    模块。每当两组模块在一个核上运行时,不需要任何的额外花费,反之需要一定的额外花费。求运行完n个模块所需的最少时间。solution:    网络流最小割    这道题的本质就是求一个分组方案,在核A上面运行一组,在核B上面运行为一组。然后求其最小花费。所以可以转换为一个最小割    模型来求解。note:    * 像这种用最小的费用将对象划分成两个集合的问题,常常可以转换成最小割后顺利解决。*/#include <iostream>#include <cstring>#include <cstdio>#include <vector>#include <queue>using namespace std;const int maxn = 20000 + 5;const int INF = 0x3f3f3f3f;struct Edge{    int to, cap, rev;    Edge(int to_, int cap_, int rev_):to(to_),cap(cap_),rev(rev_){}};vector<Edge> G[maxn];int level[maxn], iter[maxn];int n, m;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 dinic(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 main(){    //freopen("in.txt", "r", stdin);    while(~scanf("%d%d", &n, &m)) {        for(int i = 0; i < maxn; i++)   G[i].clear();        int s = n, t = n + 1;        int a, b;        for(int i = 0; i < n; i++) {            scanf("%d%d", &a, &b);            add_edge(s, i, b);            add_edge(i, t, a);  //费用a是模块在S当中运行的费用,要求割的话当然是将其和t连接起来,上面同理。        }        int u, v, cost;        for(int i = 0; i < m; i++) {            scanf("%d%d%d", &u, &v, &cost);            u--;    v--;            add_edge(u, v, cost);            add_edge(v, u, cost);        }        printf("%d\n", dinic(s,t));    }    return 0;}

0 0
原创粉丝点击