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 }

 

posted @ 2016-09-06 16:25 sagitta 阅读(...) 评论(...) 编辑 收藏