UVa 753 - A Plug for UNIX(最大流)
阿新 • • 發佈:2018-08-26
printf ron 所有 ont flow new 使用 string can
因此一個插頭類型為B的設備插上這種轉換器之後就“變成”了一個插頭類型為X的設備。
轉換器可以級聯使用,例如插頭類型為A的設備依次接上A->B,B->C,C->D這3個轉換器之後會“變成”插頭類型為D的設備。
要求插的設備盡量多。問最少剩幾個不匹配的設備。
方法是建立有向圖G,結點表示插頭類型,邊表示轉換器,然後使用Floyd算法,
計算出任意一種插頭類型a是否能轉化為另一種插頭類型b。
接下來構造網絡:設設備i對應的插頭類型編號為device[i],插座i對應的插頭類型編號為recep[i],
則源點s到所有device[i]連一條弧,容量為1,然後所有recep[i]到匯點t連一條弧,容量為1,
對於所有設備i和插座j,如果device[i]可以轉化為recep[j],則從device[i]連一條弧到recep[j],容量為1,
最後求s-t最大流,答案就是m減去最大流量。
鏈接:
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=694
題意:
有n個插座,m個設備和k(n,m,k≤100)種轉換器,每種轉換器都有無限多。已知每個插座的類型,每個設備的插頭類型,
以及每種轉換器的插座類型和插頭類型。插頭和插座類型都用不超過24個字母表示,插頭只能插到類型名稱相同的插座中。
例如,有4個插座,類型分別為A, B, C, D;有5個設備,插頭類型分別為B, C, B, B, X;
還有3種轉換器,分別是B->X,X->A和X->D。這裏用B->X表示插座類型為B,插頭類型為X,
因此一個插頭類型為B的設備插上這種轉換器之後就“變成”了一個插頭類型為X的設備。
轉換器可以級聯使用,例如插頭類型為A的設備依次接上A->B,B->C,C->D這3個轉換器之後會“變成”插頭類型為D的設備。
要求插的設備盡量多。問最少剩幾個不匹配的設備。
分析:
首先要註意的是:k個轉換器中涉及的插頭類型不一定是接線板或者設備中出現過的插頭類型。
在最壞情況下,100個設備,100個插座,100個轉換器最多會出現400種插頭。
當然,400種插頭的情況肯定是無解的,但是如果編碼不當,這樣的情況可能會讓程序出現下標越界等運行錯誤。
轉換器有無限多,所以可以獨立計算出每個設備i是否可以接上0個或多個轉換器之後插到第j個插座上,
方法是建立有向圖G,結點表示插頭類型,邊表示轉換器,然後使用Floyd算法,
計算出任意一種插頭類型a是否能轉化為另一種插頭類型b。
接下來構造網絡:設設備i對應的插頭類型編號為device[i],插座i對應的插頭類型編號為recep[i],
則源點s到所有device[i]連一條弧,容量為1,然後所有recep[i]到匯點t連一條弧,容量為1,
對於所有設備i和插座j,如果device[i]可以轉化為recep[j],則從device[i]連一條弧到recep[j],容量為1,
最後求s-t最大流,答案就是m減去最大流量。
代碼:
1 //Dinic版 2 #include <cstdio> 3#include <cstring> 4 #include <string> 5 #include <map> 6 #include <vector> 7 #include <queue> 8 using namespace std; 9 10 /// 結點下標從0開始,註意maxn 11 struct Dinic { 12 static const int maxn = 1e3 + 5; 13 static const int INF = 0x3f3f3f3f; 14 struct Edge { 15 int from, to, cap, flow; 16 }; 17 18 int n, m, s, t; // 結點數,邊數(包括反向弧),源點編號和匯點編號 19 vector<Edge> edges; // 邊表。edges[e]和edges[e^1]互為反向弧 20 vector<int> G[maxn]; // 鄰接表,G[i][j]表示結點i的第j條邊在e數組中的序號 21 bool vis[maxn]; // BFS使用 22 int d[maxn]; // 從起點到i的距離 23 int cur[maxn]; // 當前弧下標 24 25 void init(int n) { 26 this->n = n; 27 edges.clear(); 28 for(int i = 0; i < n; i++) G[i].clear(); 29 } 30 void AddEdge(int from, int to, int cap) { 31 edges.push_back((Edge){from, to, cap, 0}); 32 edges.push_back((Edge){to, from, 0, 0}); 33 m = edges.size(); 34 G[from].push_back(m-2); 35 G[to].push_back(m-1); 36 } 37 bool BFS() { 38 memset(vis, 0, sizeof(vis)); 39 queue<int> Q; 40 Q.push(s); 41 vis[s] = 1; 42 d[s] = 0; 43 while(!Q.empty()) { 44 int x = Q.front(); Q.pop(); 45 for(int i = 0; i < G[x].size(); i++) { 46 Edge& e = edges[G[x][i]]; 47 if(!vis[e.to] && e.cap > e.flow) { // 只考慮殘量網絡中的弧 48 vis[e.to] = 1; 49 d[e.to] = d[x] + 1; 50 Q.push(e.to); 51 } 52 } 53 } 54 return vis[t]; 55 } 56 int DFS(int x, int a) { 57 if(x == t || a == 0) return a; 58 int flow = 0, f; 59 for(int& i = cur[x]; i < G[x].size(); i++) { // 從上次考慮的弧 60 Edge& e = edges[G[x][i]]; 61 if(d[x]+1 == d[e.to] && (f=DFS(e.to, min(a, e.cap-e.flow))) > 0) { 62 e.flow += f; 63 edges[G[x][i]^1].flow -= f; 64 flow += f; 65 a -= f; 66 if(a == 0) break; 67 } 68 } 69 return flow; 70 } 71 int Maxflow(int s, int t) { 72 this->s = s; this->t = t; 73 int flow = 0; 74 while(BFS()) { 75 memset(cur, 0, sizeof(cur)); 76 flow += DFS(s, INF); 77 } 78 return flow; 79 } 80 vector<int> Mincut() { // 在Maxflow之後調用 81 vector<int> ans; 82 for(int i = 0; i < edges.size(); i++) { 83 Edge& e = edges[i]; 84 if(vis[e.from] && !vis[e.to] && e.cap > 0) ans.push_back(i); 85 } 86 return ans; 87 } 88 }; 89 90 const int UP = 100 + 5; 91 int recep[UP], device[UP]; 92 bool can[UP*4][UP*4]; 93 map<string,int> ids; 94 Dinic dc; 95 96 int id(string s) { 97 if(ids.count(s)) return ids[s]; 98 int i = ids.size(); 99 return ids[s] = i; 100 } 101 102 void floyd() { 103 int n = ids.size(); 104 for(int i = 0; i < n; i++) can[i][i] = true; 105 for(int k = 0; k < n; k++) { 106 for(int i = 0; i < n; i++) { 107 for(int j = 0; j < n; j++) { 108 can[i][j] |= can[i][k] && can[k][j]; 109 } 110 } 111 } 112 } 113 114 int main() { 115 int T, n, m, k; 116 char s[24+5], s2[24+5]; 117 scanf("%d", &T); 118 while(T--) { 119 ids.clear(); 120 memset(can, false, sizeof(can)); 121 scanf("%d", &n); 122 for(int i = 0; i < n; i++) { 123 scanf("%s", s); 124 recep[i] = id(s); 125 } 126 scanf("%d", &m); 127 for(int i = 0; i < m; i++) { 128 scanf("%s%s", s2, s); 129 device[i] = id(s); 130 } 131 scanf("%d", &k); 132 for(int i = 0; i < k; i++) { 133 scanf("%s%s", s, s2); 134 can[id(s)][id(s2)] = true; 135 } 136 137 floyd(); 138 int V = ids.size(); 139 dc.init(V+2); 140 for(int i = 0; i < m; i++) dc.AddEdge(V, device[i], 1); 141 for(int i = 0; i < n; i++) dc.AddEdge(recep[i], V+1, 1); 142 for(int i = 0; i < m; i++) { 143 for(int t = 0; t < n; t++) { 144 if(!can[device[i]][recep[t]]) continue; 145 dc.AddEdge(device[i], recep[t], 1); 146 } 147 } 148 printf("%d\n", m - dc.Maxflow(V, V+1)); 149 if(T) printf("\n"); 150 } 151 return 0; 152 }
1 //ISAP版 2 #include <cstdio> 3 #include <cstring> 4 #include <string> 5 #include <map> 6 #include <vector> 7 #include <queue> 8 using namespace std; 9 10 /// 結點下標從0開始,註意maxn 11 struct ISAP { 12 static const int maxn = 1e3 + 5; 13 static const int INF = 0x3f3f3f3f; 14 struct Edge { 15 int from, to, cap, flow; 16 }; 17 18 int n, m, s, t; // 結點數,邊數(包括反向弧),源點編號和匯點編號 19 vector<Edge> edges; // 邊表。edges[e]和edges[e^1]互為反向弧 20 vector<int> G[maxn]; // 鄰接表,G[i][j]表示結點i的第j條邊在e數組中的序號 21 bool vis[maxn]; // BFS使用 22 int d[maxn]; // 從起點到i的距離 23 int cur[maxn]; // 當前弧下標 24 int p[maxn]; // 可增廣路上的上一條弧 25 int num[maxn]; // 距離標號計數 26 27 void init(int n) { 28 this->n = n; 29 edges.clear(); 30 for(int i = 0; i < n; i++) G[i].clear(); 31 } 32 void AddEdge(int from, int to, int cap) { 33 edges.push_back((Edge){from, to, cap, 0}); 34 edges.push_back((Edge){to, from, 0, 0}); 35 m = edges.size(); 36 G[from].push_back(m-2); 37 G[to].push_back(m-1); 38 } 39 bool BFS() { 40 memset(vis, 0, sizeof(vis)); 41 queue<int> Q; 42 Q.push(t); 43 vis[t] = 1; 44 d[t] = 0; 45 while(!Q.empty()) { 46 int x = Q.front(); Q.pop(); 47 for(int i = 0; i < G[x].size(); i++) { 48 Edge& e = edges[G[x][i]^1]; 49 if(!vis[e.from] && e.cap > e.flow) { 50 vis[e.from] = 1; 51 d[e.from] = d[x] + 1; 52 Q.push(e.from); 53 } 54 } 55 } 56 return vis[s]; 57 } 58 int Augment() { 59 int x = t, a = INF; 60 while(x != s) { 61 Edge& e = edges[p[x]]; 62 a = min(a, e.cap-e.flow); 63 x = edges[p[x]].from; 64 } 65 x = t; 66 while(x != s) { 67 edges[p[x]].flow += a; 68 edges[p[x]^1].flow -= a; 69 x = edges[p[x]].from; 70 } 71 return a; 72 } 73 int Maxflow(int s, int t) { 74 this->s = s; this->t = t; 75 int flow = 0; 76 BFS(); 77 memset(num, 0, sizeof(num)); 78 for(int i = 0; i < n; i++) num[d[i]]++; 79 int x = s; 80 memset(cur, 0, sizeof(cur)); 81 while(d[s] < n) { 82 if(x == t) { 83 flow += Augment(); 84 x = s; 85 } 86 int ok = 0; 87 for(int i = cur[x]; i < G[x].size(); i++) { 88 Edge& e = edges[G[x][i]]; 89 if(e.cap > e.flow && d[x] == d[e.to] + 1) { // Advance 90 ok = 1; 91 p[e.to] = G[x][i]; 92 cur[x] = i; // 註意 93 x = e.to; 94 break; 95 } 96 } 97 if(!ok) { // Retreat 98 int m = n-1; // 初值註意 99 for(int i = 0; i < G[x].size(); i++) { 100 Edge& e = edges[G[x][i]]; 101 if(e.cap > e.flow) m = min(m, d[e.to]); 102 } 103 if(--num[d[x]] == 0) break; // gap優化 104 num[d[x] = m+1]++; 105 cur[x] = 0; // 註意 106 if(x != s) x = edges[p[x]].from; 107 } 108 } 109 return flow; 110 } 111 vector<int> Mincut() { // 在Maxflow之後調用 112 BFS(); 113 vector<int> ans; 114 for(int i = 0; i < edges.size(); i++) { 115 Edge& e = edges[i]; 116 if(!vis[e.from] && vis[e.to] && e.cap > 0) ans.push_back(i); 117 } 118 return ans; 119 } 120 }; 121 122 const int UP = 100 + 5; 123 int recep[UP], device[UP]; 124 bool can[UP*4][UP*4]; 125 map<string,int> ids; 126 ISAP is; 127 128 int id(string s) { 129 if(ids.count(s)) return ids[s]; 130 int i = ids.size(); 131 return ids[s] = i; 132 } 133 134 void floyd() { 135 int n = ids.size(); 136 for(int i = 0; i < n; i++) can[i][i] = true; 137 for(int k = 0; k < n; k++) { 138 for(int i = 0; i < n; i++) { 139 for(int j = 0; j < n; j++) { 140 can[i][j] |= can[i][k] && can[k][j]; 141 } 142 } 143 } 144 } 145 146 int main() { 147 int T, n, m, k; 148 char s[24+5], s2[24+5]; 149 scanf("%d", &T); 150 while(T--) { 151 ids.clear(); 152 memset(can, false, sizeof(can)); 153 scanf("%d", &n); 154 for(int i = 0; i < n; i++) { 155 scanf("%s", s); 156 recep[i] = id(s); 157 } 158 scanf("%d", &m); 159 for(int i = 0; i < m; i++) { 160 scanf("%s%s", s2, s); 161 device[i] = id(s); 162 } 163 scanf("%d", &k); 164 for(int i = 0; i < k; i++) { 165 scanf("%s%s", s, s2); 166 can[id(s)][id(s2)] = true; 167 } 168 169 floyd(); 170 int V = ids.size(); 171 is.init(V+2); 172 for(int i = 0; i < m; i++) is.AddEdge(V, device[i], 1); 173 for(int i = 0; i < n; i++) is.AddEdge(recep[i], V+1, 1); 174 for(int i = 0; i < m; i++) { 175 for(int t = 0; t < n; t++) { 176 if(!can[device[i]][recep[t]]) continue; 177 is.AddEdge(device[i], recep[t], 1); 178 } 179 } 180 printf("%d\n", m - is.Maxflow(V, V+1)); 181 if(T) printf("\n"); 182 } 183 return 0; 184 }
UVa 753 - A Plug for UNIX(最大流)