一.原题链接: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);
}