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
其次。。注意边数
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
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 }