【noip模拟】最小点覆盖

Time Limit: 1000ms      Memory Limit: 128MB  

Description

最小点覆盖是指在二分图中,用最小的点集覆盖所有的边。当然,一个二分图的最小点覆盖可能有很多种。

现在给定一个二分图,请你把图中的点分成三个集合:

如果在任何一种最小点覆盖中都不包含这个点,则认为该点属于N集合。

如果在任何一种最小点覆盖中都包含这个点,则认为该点属于A集合。

如果一个点既不属于N集合,又不属于A集合,则认为该点属于E集合。

 

Input

第一行包含三个整数n, m, k,分别表示二分图A侧点的数量,二分图B侧点的数量,边的数量。

接下来k行,每行两个整数i, j,分别表示二分图A侧第i号点与二分图B侧第j号点有连边。

数据保证无重边。

 

Output

第一行输出一个长度为n的字符串,其中第i个字符表示二分图A侧第i个点所属的集合。

第二行输出一个长度为m的字符串,其中第i个字符表示二分图B侧第i个点所属的集合。

 

Sample Input

11 9 22

1 1

1 2

1 3

1 8

1 9

2 1

2 3

3 2

3 4

4 3

4 5

5 2

5 4

5 6

6 6

6 7

7 5

7 7

8 7

9 7

10 7

11 7

 

Sample Output

AEEEEEENNNN

EEEEEEANN

 

HINT

对于10%的数据,$1≤n,m≤5$

对于40%的数据,$1≤n,m≤100$

对于100%的数据,$1≤n,m≤1000, 0≤k≤n∗m$

 

 

[吐槽]

  场上?嗯。。大眼瞪小眼qwq

 

[题解]

  嗯首先码一下最小点覆盖的相关知识

  König定理

  一个二分图中最大的匹配数=该图中最小点覆盖数

  (写得比较长所以就拎出来啦不然对不起自己就是这样哈哈)

  http://www.cnblogs.com/yoyoball/p/7632871.html

 

  从链接回到这道题

  铺垫什么的。。好像略微有点多不过。。

  嗯不管了

  然后我们就可以得出一个结论:

  如果一个点没有任何一条匹配边连到,那么这个点肯定不在最小点覆盖中

  从而与它相连的点必定要在最小点覆盖中(不然这两点之间的连边就不能覆盖到了)

  而对于一个必定在最小点覆盖中的点,与它的匹配点必定不在最小点覆盖中

 

  然后就这样顺着遍历同时标记就好啦

  对于那些没有被标记到的点,肯定就是属于E的啦

  好的于是在漫长的铺垫之后这题终于解决啦ovo

  (果然把最小点覆盖的东西拎出来之后清爽了很多哈哈哈)

 

[一些细节]

  首先。。要用long long

  其次。。注意边数

 

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 using namespace std;
 5 const int MAXN=1010*2;
 6 struct xxx
 7 {
 8     int y,next;
 9 }a[1010*1010*2];
10 char mark[MAXN];
11 bool vis[MAXN];
12 int h[MAXN],match[MAXN];
13 int n,m,tot,k,ans;
14 int add(int x,int y);
15 bool dfs(int x);
16 int solve();
17 int work(int x,int op);
18 
19 int main()
20 {
21 //    freopen("a.in","r",stdin);
22 
23     int x,y;
24     scanf("%d%d%d",&n,&m,&k);
25     memset(h,-1,sizeof(h));
26     tot=0;
27     for (int i=1;i<=k;++i)
28     {
29         scanf("%d%d",&x,&y);
30         add(x,n+y); add(n+y,x);
31     }
32     memset(match,0,sizeof(match));
33     for (int i=1;i<=n+m;++i) mark[i]='E';
34     for (int i=1;i<=n;++i)
35         if (!match[i])
36         {
37             memset(vis,false,sizeof(vis));
38             if (dfs(i)) ++ans;
39         }
40 //    for (int i=1;i<=n;++i) printf("%d ",match[i]-n);
41     solve();
42     for (int i=1;i<=n;++i) printf("%c",mark[i]);
43     printf("\n");
44     for (int i=n+1;i<=n+m;++i) printf("%c",mark[i]);
45 }
46 
47 int add(int x,int y)
48 {
49     a[++tot].y=y; a[tot].next=h[x]; h[x]=tot;
50 }
51 
52 bool dfs(int x)
53 {
54     int u;
55     for (int i=h[x];i!=-1;i=a[i].next)
56     {
57         u=a[i].y;
58         if (vis[u]) continue;
59         vis[u]=true;
60         if (!match[u]||dfs(match[u]))
61         {
62             match[x]=u;
63             match[u]=x;
64             return true;
65         }
66     }
67     return false;
68 }
69 
70 int solve()
71 {
72     for (int i=1;i<=n+m;++i)
73     {
74         if (!match[i]) 
75             mark[i]='N',work(i,0);
76     }
77 }
78 
79 int work(int x,int op)
80 {
81     int u;
82     if (op==1) 
83     {
84         mark[x]='A';
85         work(match[x],0);
86         return 0;
87     }
88     mark[x]='N';
89     for (int i=h[x];i!=-1;i=a[i].next)
90     {
91         u=a[i].y;
92         if (mark[u]=='E') work(u,1);
93     }
94 }
挫挫滴代码

 

posted @ 2017-10-03 21:44  yoyoball  阅读(751)  评论(2编辑  收藏  举报