题解 UVA753 【UNIX插头 A Plug for UNIX】
题目简述有 n 个插座,m 个设备和 k (n,m,k ≤ 100) 种转换器,每种转换器有无限多。已知每个插座的类型,每个设备的插头类型,以及每种转换器的插座类型和插头类型。插头和插座类型都用不超过 2424 个字母表示,插座只能插到类型名称相同的插座中。 例如,有 4 个插座,类型分别为 A,B,C,D;有 5 个设备,插头类型分别为 B,C,B,B,X;还有三种转换器,分别是 B->X,X->A 和 X->D。这里用 B -> X 表示插座类型为 B,插头类型为 X,因此一个插座类型为 B 的设备插上这种转换器之后就 “变成” 了一个插头类型为 X 的设备。转换器可以级联使用,例如插头类型为 A 的设备依次接上 A->B,B->C,C->D 这 3 个转换器之后会 “变成” 插头类型为 D 的设备。 要求插的设备尽量多。问最少剩几个不匹配的设备。 主要思路 :最大流 (此处采用Dinic算法)Dinic的模板就不仔细讲了,有需要的的同学去网络最大流题解中去看,我这里的Dinic是从第一篇题解中学来的,代码有些相似。 这道题最重要的是建图(似乎网络流的题都是这样吧)。 我们建立一个 s = 0 作为源点,既然我们要从抽象的从设备到插座连边,也就是说从设备流入图中,既然我们每个设备只能算 1 ,我们就讲 s 向每一个设备连一条容量为 1 的边。相似的,我们要流到每个插座,最终插座流向汇点 t = n + m + k + 1(n + m + k是题目中所给的可能最大的节点数,为了不重复,我们定的大一些),便于统计答案。 然后处理插座,设备与转换器的关系。 首先是设备,设备可以直接连到插座上,也可以连到转换器上,我们就把接口名字相同的连接起来。然后处理转换器,转换器还可以连转换器,也可以直接连到插座上,也是把名字相同的连接起来,切记,不要把同一个转换器首尾连接(好像可能性不大)。 然后跑个最大流,源点 s 汇点 t。 最后,UVa的毒瘤输出,,,注意代码最后的main函数,,, code#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <string> using namespace std; #define go(i,j,n,k) for(int i = j; i <= n; i += k) #define rep(i,x) for(int i = h[x]; i != -1; i = e[i].nxt) #define curep(i,x) for(int i = cur[x]; i != -1; i = e[i].nxt) #define mn 100010 #define inf 1 << 30 inline int read(){ int x = 0,f = 1; char ch = getchar(); while(ch > '9' || ch < '0') { if(ch == '-') f = -f; ch = getchar(); } while(ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); } return x * f; } int n,K; struct edge { int v,nxt,w; } e[mn << 1]; int h[mn],p = -1; inline void add(int a,int b,int c) { e[++p].nxt = h[a],h[a] = p; e[p].v = b,e[p].w = c; e[++p].nxt = h[b],h[b] = p; e[p].v = a,e[p].w = 0; } int dep[mn],cur[mn]; string na[mn],naa[mn],name1[mn],name2[mn]; inline bool bfs(int s,int t) { go(i,n + m + K + 1,1) dep[i] = inf; go(i,1) cur[i] = h[i]; queue<int> q; dep[s] = 0; q.push(s); while(!q.empty()) { int x = q.front(); q.pop(); rep(i,x) { int v = e[i].v,w = e[i].w; if(dep[v] >= inf && w) { dep[v] = dep[x] + 1; q.push(v); } } } if(dep[t] < inf) return true; return false; } int dfs(int x,int t,int lim) { if(!lim || x == t) return lim; int flow = 0,f = 0; curep(i,x) { int v = e[i].v,w = e[i].w; cur[x] = i; if(dep[v] == dep[x] + 1 && (f = dfs(v,t,min(lim,w)))) { flow += f; lim -= f; e[i].w -= f; e[i ^ 1].w += f; if(!lim) break; } } return flow; } inline int Dinic(int s,int t) { int maxflow = 0; while(bfs(s,t)) maxflow += dfs(s,inf); return maxflow; } inline void solve() { n = read(); go(i,1,1) { cin >> na[i]; } m = read(); go(i,1) { string tmp; cin >> tmp; cin >> naa[i]; } K = read(); go(i,K,1) { cin >> name1[i] >> name2[i]; } int s = 0,t = n + m + K + 1; go(i,1) { add(i,1); } go(i,1) { add(s,i + n,1); go(j,1) { if(naa[i] == na[j]) add(i + n,1); } go(j,1) { if(naa[i] == name1[j]) add(i + n,j + n + m,1e9); } } go(i,1) { go(j,1) { if(name2[i] == na[j]) add(i + n + m,1e9); } go(j,1) { if(name2[i] == name1[j] && i != j) { add(i + n + m,1e9); } } } int ans = Dinic(s,t); cout << m - ans << "n"; } inline void init() { memset(h,-1,sizeof h); p = -1; } int main(){ int T = read(); while(T--) { init(); solve(); if(T) puts(""); } return 0; } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |