A - ACM Computer Factory POJ - 3436(网络流 - 最大流 - 拆点)

10 篇文章 0 订阅
2 篇文章 0 订阅

题目链接:https://vjudge.net/contest/68128#problem/A
算法:最大流 - 拆点
思路:把每台机器拆成两个点,中间用一条边连通,并将容量设为该机器的生成电脑的速度,通过机器的产出零件 和 机器的输入零件 来建边,不同机器之间的边容量设为无穷大。从而转化为最大流问题。输出时,将容量比原来小的且除源点汇点和拆点中的边以及反向边外的边输出即可。

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <math.h>
#define pi acos(-1)
#define fastio ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
const int INF = 0x3f3f3f3f;
const LL ll_INF = 0x3f3f3f3f3f3f3f3f;
const int maxn = 50 + 10;
const int maxp = 10 + 10;

int Q[maxn], S[maxn][maxp], D[maxn][maxp];

int s, t;
int head[maxn*maxn], cnt=0;
int dis[maxp*2];

struct Edge
{
    int from, to, next, cap;
}es[maxn*maxn*2], coe[maxn*maxn*2], link[maxn*maxn*2];

void init()
{
    memset(head, -1, sizeof(head));
}

void add(int u, int v, int vol)
{
    es[cnt].from = u;
    es[cnt].to = v;
    es[cnt].cap = vol;
    es[cnt].next = head[u]; coe[cnt] = es[cnt];
    head[u] = cnt++;


    es[cnt].from = v;
    es[cnt].to = u;
    es[cnt].cap = 0;
    es[cnt].next = head[v]; coe[cnt] = es[cnt];
    head[v] = cnt++;
}

bool BFS()
{
    queue<int> que;
    memset(dis, -1, sizeof(dis));
    dis[s] = 0;
    que.push(s);
    int cur, v;
    while(!que.empty())
    {
        cur = que.front(); que.pop();
        for(int i=head[cur]; i!=-1; i=es[i].next){
            v = es[i].to;
            if(dis[v]==-1 && es[i].cap>0){
                dis[v] = dis[cur]+1;
                que.push(v);
            }
        }
    }
    if(dis[t] == -1) return false;
    else return true;
}

int DFS(int cur, int low)
{
    int res=0;
    if(cur == t) return low;
    for(int i=head[cur]; i!=-1; i=es[i].next){
        if(dis[es[i].to]==dis[cur]+1
        && es[i].cap>0
        && (res = DFS(es[i].to, min(low, es[i].cap))) ){
            es[i].cap -= res;
            es[i^1].cap += res;
            return res;
        }
    }
    return 0;
}

int main()
{
    init();
    int P, N;
    scanf("%d%d", &P, &N);
    s = 0; t = 2*N+1;
    for(int i=1; i<=N; i++){
        scanf("%d", &Q[i]);
        int flag1=0, flag2=0;
        for(int j=1; j<=P; j++){
            scanf("%d", &S[i][j]);
            if(S[i][j] == 1) flag1=1;
        }
        if(flag1 == 0) add(s, 2*i-1, INF);

        for(int j=1; j<=P; j++){
            scanf("%d", &D[i][j]);
            if(D[i][j] == 0) flag2=1;
        }
        if(flag2 == 0) add(2*i, t, INF);
    }

    for(int i=1; i<=N; i++){
        for(int j=1; j<=N; j++){
            if(i == j) {
                add(i*2-1, i*2, Q[i]);
                continue;
            }

            int flag = 0;
            for(int k=1; k<=P; k++){
                if(!(D[i][k]==S[j][k] || S[j][k]==2)){
                    flag = 1; break;
                }
            }
            if(!flag) add(2*i, 2*j-1, INF);
        }
    }

    int ans=0 , tmp=0;
    while(BFS()){
        if(tmp = DFS(s, INF))
            ans += tmp;
    }
    printf("%d ", ans);

    int tot=0;
    for(int i=0; i<cnt; i++){
        if(es[i].to%2==0 && es[i].from==es[i].to-1) continue;
        if(coe[i].cap == 0 || coe[i].from==s ||coe[i].to==t) continue;
        if(coe[i].cap > es[i].cap) {
            link[++tot].from = (es[i].from+1)/2;
            link[tot].to = (es[i].to+1)/2;
            link[tot].cap = coe[i].cap - es[i].cap;
        }
    }
    printf("%d\n", tot);
    for(int i=1; i<=tot; i++){
        printf("%d %d %d\n", link[i].from, link[i].to, link[i].cap);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值