POJ - 3469 Dual Core CPU (最小割)

(点击此处查看原题)

题意介绍

在一个由核A和核B组成的双核CPU上执行N个任务,任务i在核A上执行,花费Ai,在核B上执行,花费为Bi,而某两个任务之间可能需要进数据交互,如果两个任务在同一个核上执行,那么数据交互将没有花费,如果在不同核上执行,将产生wi的花费,问将n个任务全部执行产生的最小花费 。

解题思路

题目要求将n个任务分配为两个不同的集合,使得执行n个任务总花费最少,这类的题目我们一般将其转化为最小割问题,即花费最小的代价将n个点分为两部分。建图如下:

1)由源点向每个任务建一条容量为Ai的边

2)由每个任务向汇点建一条容量为Bi的边

3)对于不在同一核上运行的两个任务a,b,将产生额外的w花费,我们在a,b之间建两条容量为w的边,分为是a->b,b->a

最后我们在构建的图中跑最小割并输出最小割即可。

代码区

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#include<string>
#include<fstream>
#include<vector>
#include<stack>
#include <map>
#include <iomanip>

#define bug cout << "**********" << endl
#define show(x, y) cout<<"["<<x<<","<<y<<"] "
#define LOCAL = 1;
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const ll mod = 1e9 + 7;
const int Max = 4e6 + 10;

struct Edge
{
    int to, flow, next;
} edge[Max << 1];

int n, m, s, t;
int head[Max], tot;
int dis[Max], cur[Max];

void init()
{
    memset(head, -1, sizeof(head));
    tot = 0;
    s = 0;
    t = n + 1;
}

void add(int u, int v, int flow)
{
    edge[tot].to = v;
    edge[tot].flow = flow;
    edge[tot].next = head[u];
    head[u] = tot++;
}

bool bfs()
{
    memset(dis, -1, sizeof(dis));
    queue<int> q;
    dis[s] = 0;
    q.push(s);
    while (!q.empty())
    {
        int u = q.front();
        q.pop();
        for (int i = head[u]; i != -1; i = edge[i].next)
        {
            int v = edge[i].to;
            if (edge[i].flow > 0 && dis[v] == -1)
            {
                dis[v] = dis[u] + 1;
                if (v == t)
                    return true;
                q.push(v);
            }
        }
    }
    return false;
}

int dfs(int u, int flow_in)
{
    if (u == t)
        return flow_in;
    int flow_out = 0;
    for (int i = cur[u]; i != -1; i = edge[i].next)
    {
        cur[u] = i;
        int v = edge[i].to;
        if (dis[v] == dis[u] + 1 && edge[i].flow > 0)
        {
            int flow = dfs(v, min(flow_in, edge[i].flow));
            if (flow == 0)
                continue;
            flow_in -= flow;
            flow_out += flow;
            edge[i].flow -= flow;
            edge[i ^ 1].flow += flow;
            if (flow_in == 0)
                break;
        }
    }
    return flow_out;
}

int Dinic(int ans)
{
    int sum = 0;
    while (bfs())
    {
        for (int i = 0; i <= ans; i++)
            cur[i] = head[i];
        sum += dfs(s, inf);
    }
    return sum;
}

int main()
{
#ifdef LOCAL
    //freopen("input.txt", "r", stdin);
    //freopen("output.txt", "w", stdout);
#endif
    while (scanf("%d%d", &n, &m) != EOF)
    {
        init();
        for (int i = 1, a, b; i <= n; i++)
        {
            scanf("%d%d", &a, &b);
            add(s, i, a);
            add(i, s, 0);
            add(i, t, b);
            add(t, i, 0);
        }
        for(int i =1, u, v, flow; i <= m ;i ++)
        {
            scanf("%d%d%d",&u,&v,&flow);
            add(u,v,flow);
            add(v,u,flow);
        }
        printf("%d\n",Dinic(n+1));
    }
    return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/winter-bamboo/p/11391925.html
今日推荐