poj 3469 Dual Core CPU(dinic算法)

题意:

有一些模块(modules)和一个双核处理器,一个模块可以在任意一个核上处理,每个核对应每个模块有个开销。现在有一些模块间需要数据交换,如果需要数据交换的模块在一个核上处理,则不需要额外开销,否则需要加上一个开销。现在需要完成所有模块,问最小需要多少开销。

如果没有这个额外的开销,那么每个模块只要选择开销小的那个核就行了。额外的开销给选择加上了限制。

题解:

最小割模型。

S和T分别表示两个核,每个模块和S,T连边求最小割就是了~

#include <cstdio>
#include <iostream>
#include <cstring>
#include <string>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <vector>
#include <set>
#include <list>
#include <queue>
#include <map>
#include <stack>
using namespace std;
#define L(i) i<<1
#define R(i) i<<1|1
#define INF  0x3f3f3f3f
#define pi acos(-1.0)
#define eps 1e-3
#define maxn 200010
#define MOD 1000000007

struct Edge
{
    int to, val, next;
} edge[2000000];
int n, m, tot;
int head[20100], level[20100], cur[20100];

void add_edge(int from, int to, int val)
{
    edge[tot].to = to;
    edge[tot].val = val;
    edge[tot].next = head[from];
    head[from] = tot++;
    edge[tot].to = from;
    edge[tot].val = 0;
    edge[tot].next = head[to];
    head[to] = tot++;
}
int bfs(int s,int t)
{
    queue<int> que;
    que.push(s);
    memset(level,-1,sizeof(level));
    level[s] = 0;
    while(!que.empty())
    {
        int v = que.front();
        que.pop();
        int u = head[v];
        for(; u != -1; u = edge[u].next)
            if(edge[u].val > 0 && level[edge[u].to] == -1)
        {
            level[edge[u].to] = level[v] + 1;
            que.push(edge[u].to);
            if(edge[u].to == t)
                return 1;
        }
    }
    return 0;
}
int Find(int u,int cnt)
{
    if(u == n+1)
        return cnt;
    int result = 0,tmp = 0;
    for(int i = head[u]; i != -1 && result < cnt; i = edge[i].next)
        if(edge[i].val > 0 && level[edge[i].to] == level[u] + 1)
        {
            tmp = Find(edge[i].to,min(edge[i].val,cnt - result));
            edge[i].val -= tmp;
            edge[i^1].val += tmp;
            result += tmp;
        }
    if(!result)
        level[u] = -1;
    return result;
}
int dinic()
{
    int ans = 0;
    while(bfs(0,n+1))
        ans += Find(0,INF);
    return ans;
}
int main()
{
    while(scanf("%d%d", &n, &m) != EOF)
    {
        int a, b, c;
        memset(head, -1, sizeof(head));
        tot = 0;
        for(int i = 1; i <= n; i++)
        {
            scanf("%d%d", &a, &b);
            add_edge(0, i, a);
            add_edge(i, n+1, b);
        }
        for(int i = 1; i <= m; i++)
        {
            scanf("%d%d%d", &a, &b,&c);
            add_edge(a, b, c);
            add_edge(b, a, c);
        }
        printf("%d\n", dinic());
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值