URAL 2038 Minimum Vertex Cover
题目链接:http://acm.timus.ru/problem.aspx?space=1&num=2038
---------------------------------------------------------------------------------
题目大意: 给一个二分图 问每个点是必在$(A)$/ 可在$(E)$/ 必不在$(N)$最小点覆盖中这三种状态中的哪种
熟练地运用 最小点覆盖$=$最大匹配 这个结论是做这题的前提
然后我们可以先求除一组最大匹配
特判过样例什么的肯定是不对的
我们先从一个简单的结论代入
如果一个点是$N$ 那么和它相邻的点一定是$A$ 否则两点间的那条边无法被覆盖
那么我们如何来求$N$呢
我们知道最大匹配的那些边是没有公共点的
那么至少要用和最大匹配边数相等的点数来覆盖(每条匹配边选一个点来覆盖) 才有可能覆盖所有的边
又由于"最小点覆盖$=$最大匹配"这个结论的存在 我们选取的点只能是在最大匹配边上的点
因此所有不在最大匹配边上的点都是N点
这样边可以求出一部分的N点和A点
不过N点还有一种情况 那就是对于一个A点 和它匹配的点一定是N点
这个同样是用"最小点覆盖$=$最大匹配"这个结论
由于这个结论的存在 每条匹配边只能选一端的点放入最小点覆盖集合中 因此一端是$A$另一端就一定是$N$了
通过这些结论可以求出所有的$N$和$A$ 其余的便是$E$了
另外此题时限较紧 可以选择快速读入或者用比匈牙利算法更快的二分图匹配算法
1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 #include <algorithm> 5 using namespace std; 6 const int N = 1010, E = 1e6 + 10; 7 int firste[N << 1], nexte[E << 1], v[E << 1], ma[N << 1]; 8 bool used[N << 1], on[N << 1]; 9 int color[N << 1]; 10 int n, m, k, e; 11 int readint() 12 { 13 int re = 0; 14 char c = getchar(); 15 while(c < '0' || c > '9') 16 c = getchar(); 17 while(c >= '0' && c <= '9') 18 { 19 re = (re << 3) + (re << 1) + c - '0'; 20 c = getchar(); 21 } 22 return re; 23 } 24 void build(int x, int y) 25 { 26 nexte[++e] = firste[x]; 27 firste[x] = e; 28 v[e] = y; 29 } 30 bool dfs(int u) 31 { 32 for(int p = firste[u]; p; p = nexte[p]) 33 if(!used[v[p]]) 34 { 35 used[v[p]] = 1; 36 if(!ma[v[p]] || dfs(ma[v[p]])) 37 { 38 ma[v[p]] = u; 39 return 1; 40 } 41 } 42 return 0; 43 } 44 void hungary() 45 { 46 for(int i = 1; i <= n; ++i) 47 { 48 memset(used, 0, sizeof used); 49 dfs(i); 50 } 51 } 52 void dfs2(int u) 53 { 54 for(int p = firste[u]; p; p = nexte[p]) 55 if(!color[v[p]]) 56 { 57 color[v[p]] = 2; 58 if(!color[ma[v[p]]]) 59 { 60 color[ma[v[p]]] = 1; 61 dfs2(ma[v[p]]); 62 } 63 } 64 } 65 void print() 66 { 67 for(int i = 1; i <= n; ++i) 68 if(color[i] == 2) 69 putchar('A'); 70 else if(color[i]) 71 putchar('N'); 72 else 73 putchar('E'); 74 puts(""); 75 for(int i = n + 1; i <= n + m; ++i) 76 if(color[i] == 2) 77 putchar('A'); 78 else if(color[i]) 79 putchar('N'); 80 else 81 putchar('E'); 82 puts(""); 83 } 84 int main() 85 { 86 n = readint(); 87 m = readint(); 88 k = readint(); 89 int x, y; 90 while(k--) 91 { 92 x = readint(); 93 y = readint(); 94 build(x, n + y); 95 build(n + y, x); 96 } 97 hungary(); 98 for(int i = 1; i <= m; ++i) 99 if(ma[n + i]) 100 { 101 ma[ma[n + i]] = n + i; 102 on[n + i] = on[ma[n + i]] = 1; 103 } 104 for(int u = 1; u <= n + m; ++u) 105 if(!on[u] && !color[u]) 106 { 107 color[u] = 1; 108 dfs2(u); 109 } 110 print(); 111 return 0; 112 }