Linux 配置埠對映
阿新 • • 發佈:2020-12-08
網路流24題
洛谷題單:網路流24題
第一題:飛行員配對問題
二分圖模板題,匈牙利可以過,並且匈牙利演算法可以記錄匹配的資訊
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <queue> 5 #define N 100010 6 using namespace std; 7 int cnt, n, m, head[N], nxt[N], to[N], p[N]; 8 bool vis[N]; 9 inline int read() {View Code10 int x = 0, y = 1; 11 char c = getchar(); 12 while (c < '0' || c > '9') { 13 if (c == '-') 14 y = -1; 15 c = getchar(); 16 } 17 while (c >= '0' && c <= '9') 18 x = x * 10 + c - '0', c = getchar(); 19 return x * y; 20 } 21 voidadd(int x, int y) { 22 nxt[++cnt] = head[x]; 23 head[x] = cnt; 24 to[cnt] = y; 25 } 26 bool match(int u) { 27 for (int i = head[u]; ~i; i = nxt[i]) { 28 int v = to[i]; 29 if (vis[v]) 30 continue; 31 else 32 vis[v] = true; 33 if (p[v] == 0|| match(p[v])) { 34 p[v] = u; 35 return true; 36 } 37 } 38 return false; 39 } 40 int pipei() { 41 int ans = 0; 42 for (int i = 1; i <= m; i++) { 43 memset(vis, false, sizeof(vis)); 44 if (match(i)) 45 ans++; 46 } 47 return ans; 48 } 49 int main() { 50 cnt = -1; 51 memset(head, -1, sizeof(head)); memset(p,0,sizeof(p)); 52 m = read(); 53 n = read(); 54 int u, v; 55 while (~scanf("%d%d", &u, &v) && u+v != -2) add(u, v); 56 int k = pipei(); 57 printf("%d\n",k); 58 for(int i = m+1; i <= n; i++) 59 if(p[i] != 0) 60 printf("%d %d\n",p[i],i); 61 return 0; 62 }
第二題:太空飛行計劃問題
最小割的應用,最大權閉合子圖模板題,源點建正權,匯點建負權
最大權閉合子圖的權值和=max{被選擇的點權和}=正點權和−min{沒被選擇的正權點之和+被選擇的負權點絕對值和}
=正點權和−最小割
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <queue> 5 #include <vector> 6 #define N 10010 7 using namespace std; 8 vector<int> g[N]; 9 int cnt,n,m,s,t,head[N],nxt[N],to[N],d[N],cur[N],w[N],f[N]; 10 const int INF = 0x3f3f3f3f; 11 void add(int x, int y, int z) 12 { 13 nxt[++cnt] = head[x]; 14 head[x] = cnt; 15 to[cnt] = y; 16 w[cnt] = z; 17 } 18 bool bfs(int s, int t) 19 { 20 memset(d,-1,sizeof(d)); 21 d[s] = 0; 22 queue<int> q; 23 q.push(s); 24 while(!q.empty()) 25 { 26 int p = q.front(); q.pop(); 27 for(int i = head[p]; ~i; i = nxt[i]) 28 { 29 int v = to[i]; 30 if(d[v] == -1 && w[i]) 31 { 32 d[v] = d[p]+1; 33 q.push(v); 34 } 35 } 36 } 37 return d[t] != -1; 38 } 39 int dfs(int s, int flow) 40 { 41 if(s == t) return flow; 42 int ans = 0; 43 for(int i = cur[s]; ~i; i = nxt[i]) 44 { 45 int v = to[i]; 46 cur[s] = i; 47 if(d[v] == d[s]+1 && w[i]) 48 { 49 int dis = dfs(v,min(flow,w[i])); 50 if(dis) 51 { 52 w[i] -= dis; 53 w[i^1] += dis; 54 flow -= dis; 55 ans += dis; 56 if(flow == 0) break; 57 } 58 } 59 } 60 return ans; 61 } 62 int dinic(int s, int t) 63 { 64 int ans = 0; 65 while(bfs(s,t)) 66 { 67 memcpy(cur,head,sizeof(head)); 68 ans += dfs(s,INF); 69 } 70 return ans; 71 } 72 int main() 73 { 74 int sum = 0; 75 cnt = -1; memset(head,-1,sizeof(head)); 76 scanf("%d%d",&m,&n); 77 s = 0; t = n+m+1; 78 for(int i = 1; i <= m; i++) 79 { 80 int x; char c; 81 scanf("%d",&x); 82 sum += x; 83 add(s,i+n,x); add(i+n,s,0); 84 while(true) 85 { 86 scanf("%d%c",&x,&c); 87 add(i+n,x,INF); add(x,i+n,0); 88 if(c == '\n' || c == '\r') break; 89 } 90 } 91 for(int i = 1; i <= n; i++) 92 { 93 int x; 94 scanf("%d",&x); 95 add(i,t,x); add(t,i,0); 96 } 97 sum -= dinic(s,t); 98 for(int i = 1; i <= m; i++) 99 if(d[i+n] != -1) 100 printf("%d ",i); 101 puts(""); 102 for(int i = 1; i <= n; i++) 103 if(d[i] != -1) 104 printf("%d ",i); 105 puts(""); 106 printf("%d\n",sum); 107 return 0; 108 }View Code