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