题意:有若干个电器设备需要不同的适配器才能接上电源,现在你要让尽可能多的电气设备接上电源。首先你手中有n个适配器和适配器的型号,再告诉你有m个电器和他们分别对应的适配器的型号,最后还有一个商店提供买不同型号的适配器转换器,转换是单向的A B表示能把A接口转换成B接口(就是原来需要用A适配器的现在可以用B适配器当然也可以用原来的不变)超市提供的转换器数量是没有限制的,可以无限买。
思路:这道题很容易就转化为最大流问题首先一个源点连接不同的电器流量为1,不同的电器根据需要连上不同的适配器流量也为1,再根据不同适配器中能转换建立流量为INF的单向边,再根据每个每个适配器拥有的数量从没个适配器连接一条流量为其数量的边至汇点。这样图就建完了,接下来是EK算法解决问题。
代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <algorithm> 6 #include <queue> 7 #include <stack> 8 #include <utility> 9 #define LEN 510 10 #define INF 0x3f3f3f3f 11 #define ll long long 12 #define eps 1e-6 13 14 using namespace std; 15 16 int n, m, k, tn, tm, tk, cap[LEN][LEN]; 17 char rec[LEN][51], di[LEN][51], numr[LEN]; 18 19 void init(){ 20 tn = tm = tk = 0; 21 memset(numr, 0, sizeof numr); 22 memset(cap, 0, sizeof cap); 23 } 24 25 int ji(char str[]){ 26 for(int i=0; i<tn; i++){ 27 if(strcmp(rec[i], str)==0)return i; 28 } 29 return -1; 30 } 31 32 int EK(int s, int t) 33 { 34 int f, flow[LEN][LEN], a[LEN], p[LEN]; 35 queue<int> q; 36 memset(flow, 0, sizeof flow); 37 f = 0; 38 while(1){ 39 memset(a, 0, sizeof a); 40 a[s] = INF; 41 q.push(s); 42 while(!q.empty()){ 43 int u = q.front(); q.pop(); 44 for(int v=0; v<n; v++){ 45 if(!a[v] && cap[u][v]>flow[u][v]){ 46 p[v] = u; 47 q.push(v); 48 a[v] = min(a[u], cap[u][v]-flow[u][v]); 49 } 50 } 51 } 52 if(a[t] == 0)break; 53 for(int u=t; u!=s; u = p[u]){ 54 flow[p[u]][u]+=a[t]; 55 flow[u][p[u]]-=a[t]; 56 } 57 f+=a[t]; 58 } 59 return f; 60 } 61 62 int main() 63 { 64 // freopen("in.txt", "r", stdin); 65 66 int T; 67 char str[51], sstr[51]; 68 scanf("%d", &T); 69 while(T--){ 70 init(); 71 scanf("%d", &n); 72 for(int i=1; i<=n ;i++){ 73 scanf("%s", str); 74 int pos = ji(str); 75 if(pos==-1){ 76 strcpy(rec[tn], str); 77 numr[tn++] = 1; 78 } 79 else numr[pos] ++; 80 } 81 scanf("%d", &m); 82 for(int i=1; i<=m; i++){ 83 scanf("%s%s", di[i], str); 84 int pos = ji(str); 85 if(pos == -1){ 86 pos = tn; 87 strcpy(rec[tn], str); 88 numr[tn++] = 0; 89 } 90 cap[0][i] = 1; 91 cap[i][m+1+pos] = 1; 92 } 93 scanf("%d", &k); 94 for(int i=1; i<=k; i++){ 95 scanf("%s%s", str, sstr); 96 if(ji(str)==-1){ 97 strcpy(rec[tn], str); 98 numr[tn++] = 0; 99 } 100 if(ji(sstr)==-1){ 101 strcpy(rec[tn], sstr); 102 numr[tn++] = 0; 103 } 104 // cout << str << " -> " << sstr << endl; 105 cap[m+1+ji(str)][m+1+ji(sstr)] = INF; 106 } 107 for(int i=0; i<tn; i++){ 108 cap[m+1+i][m+tn+1] = numr[i]; 109 } 110 n = m+tn+2; 111 int ans = EK(0, n-1); 112 cout << m-ans << endl; 113 if(T)cout << endl; 114 } 115 return 0; 116 }