zoukankan      html  css  js  c++  java
  • 题解 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, m, 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, 0, n + m + K + 1, 1) dep[i] = inf;
    	go(i, 0, n + m + K + 1, 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, t, inf); 
    	return maxflow;
    }
    
    inline void solve() {
    	n = read();
    	go(i, 1, n, 1) {
    		cin >> na[i];
    	}
    	m = read();
    	go(i, 1, m, 1) {
    		string tmp; cin >> tmp;
    		cin >> naa[i];
    	}
    	K = read();
    	go(i, 1, K, 1) {
    		cin >> name1[i] >> name2[i];
    	}
    	int s = 0, t = n + m + K + 1;
    	go(i, 1, n, 1) {
    		add(i, t, 1);
    	} 
    	go(i, 1, m, 1) {
    		add(s, i + n, 1);
    		go(j, 1, n, 1) {
    			if(naa[i] == na[j])
    				add(i + n, j, 1);
    		}
    		go(j, 1, K, 1) {
    			if(naa[i] == name1[j])
    				add(i + n, j + n + m, 1e9);
    		}
    	}
    	go(i, 1, K, 1) {
    		go(j, 1, n, 1) {
    			if(name2[i] == na[j])
    				add(i + n + m, j, 1e9);
    		} 
    		go(j, 1, K, 1) {
    			if(name2[i] == name1[j] && i != j) {
    				add(i + n + m, j + n + m, 1e9);
    			}
    		}
    	}
    	int ans = Dinic(s, t);
    	cout << m - ans << "
    ";
    }
    inline void init() {
    	memset(h, -1, sizeof h);
    	p = -1;
    }
    int main(){
    	int T = read();
    	while(T--) {
    		init();
    		solve();
    		if(T) puts("");
    	}
    	return 0;
    }
    
  • 相关阅读:
    Codeforces 1291 Round #616 (Div. 2) B
    总结
    刷新DNS解析缓存+追踪+域名解析命令
    数学--数论--Hdu 5793 A Boring Question (打表+逆元)
    Lucene.net(4.8.0) 学习问题记录六:Lucene 的索引系统和搜索过程分析
    LeetCode 117 Populating Next Right Pointers in Each Node II
    LeetCode 116 Populating Next Right Pointers in Each Node
    test test
    LeetCode 115 Distinct Subsequences
    LeetCode 114. Flatten Binary Tree to Linked List
  • 原文地址:https://www.cnblogs.com/yizimi/p/10582041.html
Copyright © 2011-2022 走看看