POJ1087 A Plug for UNIX

一.原题链接:http://poj.org/problem?id=1087

二,题目大意:先给出N个插头,再给出M个需要插的电器,再给出k个可以转换的途径(注意可以无限次转换)。求最少剩下几个插头?

三,思路:源点和需要的插的电器所需插头相连,容量为各自出现次数,汇点和给出的插头相连,容量为各自出现的次数,之间转换的途径再相连,容量为无穷大,因为可以转换无限次。

四,代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
#include <vector>
#include <string>

using namespace std;

const int INF = 0x3f3f3f3f,
          MAX_SIZE = 402;

int s, t, maxFlow, nodeNum, cntT[MAX_SIZE], cntS[MAX_SIZE],
    RE[MAX_SIZE][MAX_SIZE], H[MAX_SIZE], EF[MAX_SIZE];
queue <int> que;
char receptacles[MAX_SIZE][26];

void init()
{
    int i, j;
    maxFlow = 0;
    s = nodeNum+1, t = nodeNum+2;
    H[s] = nodeNum+2;
    EF[s] = INF;
    EF[t] = -INF;
    for(i = 1; i <= nodeNum; i++)
        RE[s][i] = cntS[i];
    for(i = 1; i <= nodeNum; i++)
        RE[i][t] = cntT[i];
}

void Push(int cur)
{
    int i, temp;
    for(i = 1; i <= t; i++){
        temp = min(RE[cur][i], EF[cur]);
        if(temp > 0 && (cur == s || H[cur] - H[i] == 1)){
            RE[cur][i] -= temp; RE[i][cur] += temp;
            EF[cur] -= temp; EF[i] += temp;
            if(i == t)
                maxFlow += temp;
            if(i != s && i != t){
                que.push(i);
            }
        }
    }
}

void Relabel(int cur)
{
    if(cur != s && cur != t && EF[cur] > 0){
        H[cur]++;
        que.push(cur);
    }
}

void Push_Relabel(int m)
{
    init();
    int cur;
    que.push(s);
    while(!que.empty()){
        cur = que.front();
        que.pop();
        Push(cur);
        Relabel(cur);
    }
    printf("%d\n", m - maxFlow);
}

int Hash(char *buffer)
{
    int i;
    for(i = 1; i <= nodeNum; i++)
        if(!strcmp(buffer, receptacles[i]))
            return i;

    nodeNum++;
    strcpy(receptacles[nodeNum], buffer);
    return nodeNum;
}

int main()
{
    //freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);

    int u, v, i, j, n, m, k, saveM;
    char buffer1[26], buffer2[26];

    scanf("%d", &n);
    while(n--){
        scanf("%s", buffer1);
        cntT[Hash(buffer1)]++;
    }


    scanf("%d", &m);
    saveM = m;
    while(m--){
        scanf("%s %s", buffer2, buffer1);
        cntS[Hash(buffer1)]++;
    }

    scanf("%d", &k);
    while(k--){
        scanf("%s %s", buffer1, buffer2);
        u = Hash(buffer1);
        t = Hash(buffer2);
        RE[u][t] = INF;
    }

    Push_Relabel(saveM);
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值