URAL 2038 Minimum Vertex Cover

2038. Minimum Vertex Cover

Time limit: 1.0 second
Memory limit: 64 MB

A vertex cover of a graph is a set of vertices such that each edge of the graph is incident to at least one vertex of the set. A minimum vertex cover is a vertex cover with minimal cardinality.

Consider a set of all minimum vertex covers of a given bipartite graph. Your task is to divide all vertices of the graph into three sets. A vertex is in setN (“Never”) if there is no minimum vertex cover containing this vertex. A vertex is in set A (“Always”) if it is a part of every minimum vertex cover of the given graph. If a vertex belongs neither to N nor to A, it goes to the set E (“Exists”).

Input

The first line of input contains three integers nmk: the size of the first vertex set of the bipartite graph, the size of the second vertex set and the number of edges (1 ≤ nm ≤ 1000; 0 ≤ k ≤ 106). Next k lines contain pairs of numbers of vertices, connected by an edge. First number denotes a vertex from the first set, second — from the second set. Vertices in each set are numbered starting from one. No pair of vertices is connected by more than one edge.

Output

On the first line, print a sequence of n letters ‘N’, ‘E’, ‘A’ without spaces. The letter on position i corresponds to the set containing i-th vertex of the first set. The second line must contain the answer for the second vertex set in the same format.

Sample

input output
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
AEEEEEENNNN
EEEEEEANN

题解:

看了网上 http://blog.csdn.net/u011699990/article/details/45257071 的题解才会的

关键就是确定这个点是否在最小点覆盖的条件是 : 如果这个点是一个已盖点,从他相连的所有点中只要存在一个是未盖点,那么这个点一定是在最小点覆盖上的(这个结论很神奇,也很容易想通)

那么一旦确定了某个点是最小点覆盖上的点之后,他所对应的另外一个匹配点就一定不会在最小点覆盖了,如此循环,我们就能最终确定哪些点是一定在最小点覆盖上了,可以看看代码理解,代码写了注释

#include <bits/stdc++.h>
#define rep(a,b,c) for(int (a)=(b);(a)<=(c);++(a))
#define drep(a,b,c) for(int (a)=(b);(a)>=(c);--(a))
#define pb push_back
#define mp make_pair
#define sf scanf
#define pf printf
#define two(x) (1<<(x))
#define clr(x,y) memset((x),(y),sizeof((x)))
#define dbg(x) cout << #x << "=" << x << endl;
#define lowbit(x) ((x)&(-x))
const int mod = 1e9 + 7;
int mul(int x,int y){return 1LL*x*y%mod;}
int qpow(int x , int y){int res=1;while(y){if(y&1) res=mul(res,x) ; y>>=1 ; x=mul(x,x);} return res;}
inline int read(){int x=0,f=1;char ch=getchar();while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}return x*f;}
using namespace std;
const int maxn = 1e3 + 15;
vector < int > LE[maxn] , RE[maxn] ;
int linkL[maxn],linkR[maxn],N,M,K,ansL[maxn],ansR[maxn],vis[maxn];

int DFS( int x ){
	for( auto v : LE[x] ){
		if( vis[v] ) continue;
		vis[v] = 1;
		if( linkR[v] == -1 || DFS( linkR[v] ) ){
			linkL[x] = v , linkR[v] = x;
			return 1;
		}
	}
	return 0;
}

int main( int argc , char * argv[] ){
	N=read(),M=read(),K=read();
	rep(i,1,K){
		int u = read() , v = read();
		LE[u].pb( v ); RE[v].pb( u );
	}
	clr( linkL , -1 ) ; clr( linkR , -1 );
	// 进行二分图最大匹配
	rep(i,1,N){
		rep(j,1,M) vis[j]=0;
		DFS( i );
	}
	// 初始认为所有匹配的点都是 E , 对于未匹配点,加入队列中
	queue < int > Q;
	rep(i,1,N) if(~linkL[i]) ansL[i] = 1; else Q.push( i );
	rep(i,1,M) if(~linkR[i]) ansR[i] = 1; else Q.push( i + N );
	// 对于一定在最小点覆盖的点满足的条件即 : 这个匹配点连接的所有边中存在非匹配点 , 即,如果存在的话,就必须选这个点
	// 开始跑
	// 注意队列中的点都是未匹配点
	while(!Q.empty()){
		int x = Q.front() ; Q.pop();
		// 是左边的点
		if( x <= N ){
			for( auto v : LE[x] ){
				// 右边的点是一个匹配点同时没有check过
				if( ~linkR[v] && ansR[v] != 2 ){
					ansR[v] = 2; // 这个点必选
					ansL[linkR[v]] = 0; // 那么他所对应的左边的匹配点一定不选
					Q.push( linkR[v] ); // 左边那个点不选了,加入到队列中
				}
			}
		}else{
			for( auto v : RE[x - N] ){
				// 左边的点是一个匹配点同时没有check过
				if( ~linkL[v] && ansL[v] != 2 ){
					ansL[v] = 2; // 这个点必选
					ansR[linkL[v]] = 0; // 那么他所对应的右边的匹配点一定不选
					Q.push( linkL[v] + N ); // 左边那个点不选了,加入到队列中
				}
			}
		}
	}
	rep(i,1,N) if(ansL[i] == 0) putchar(‘N‘) ; else if( ansL[i] == 1 ) putchar(‘E‘) ; else putchar(‘A‘);
	puts("");
	rep(i,1,M) if(ansR[i] == 0) putchar(‘N‘) ; else if( ansR[i] == 1 ) putchar(‘E‘) ; else putchar(‘A‘);
	puts("");
	return 0;
}

  

时间: 2024-10-22 16:24:00

URAL 2038 Minimum Vertex Cover的相关文章

SCU - 4439 Vertex Cover (图的最小点覆盖集)

Vertex Cover frog has a graph with \(n\) vertices \(v(1), v(2), \dots, v(n)\) and \(m\) edges \((v(a_1), v(b_1)), (v(a_2), v(b_2)), \dots, (v(a_m), v(b_m))\). She would like to color some vertices so that each edge has at least one colored vertex. Fi

四川第七届 D Vertex Cover(二分图最小点覆盖,二分匹配模板)

Vertex Cover frog has a graph with nn vertices v(1),v(2),-,v(n)v(1),v(2),-,v(n) and mm edges (v(a1),v(b1)),(v(a2),v(b2)),-,(v(am),v(bm))(v(a1),v(b1)),(v(a2),v(b2)),-,(v(am),v(bm)). She would like to color some vertices so that each edge has at least

二分图匹配 + 最小点覆盖 - Vertex Cover

Vertex Cover Problem's Link Mean: 给你一个无向图,让你给图中的结点染色,使得:每条边的两个顶点至少有一个顶点被染色.求最少的染色顶点数. analyse: 裸的最小点覆盖问题,二分图的最大匹配,直接套模版即可. Time complexity: O(N^2) view code

PAT 1134 Vertex Cover

A vertex cover of a graph is a set of vertices such that each edge of the graph is incident to at least one vertex of the set. Now given a graph with several vertex sets, you are supposed to tell if each of them is a vertex cover or not. Input Specif

1134 Vertex Cover (25 分)

1134 Vertex Cover (25 分) A vertex cover of a graph is a set of vertices such that each edge of the graph is incident to at least one vertex of the set. Now given a graph with several vertex sets, you are supposed to tell if each of them is a vertex c

1134. Vertex Cover (25)

稍微做一点点手脚就不会超时了...还是挺简单的,考试时候也做出来了... #include<iostream> #include<string> #include<queue> #include<algorithm> using namespace std; const int inf = 99999999; int main() { int v, e; cin >> v >> e; int check[10001]; vector&

2017中国大学生程序设计竞赛 - 网络选拔赛 HDU 6150 Vertex Cover 二分图,构造

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6150 题意:"最小点覆盖集"是个NP完全问题 有一个近似算法是说-每次选取度数最大的点(如果有多个这样的点,则选择最后一个) 让你构造一个图,使得其近似算法求出来点数是你给定的覆盖点数的至少3倍. 解法: 可以把左边的点编号1~n,将左边的点进行n次分块,第i次分块中每块的大小为i,对于每一块的点,都在右边创建一个新节点与这些点相连. ①右边的点的度数为n,n-1,n-2,...,n/2,

scu oj 4439 : Vertex Cover(2015年四川省程序ACM设计竞赛D题 )

一般图的最小点覆盖问题是是一个npc问题,目前哈没有比较好的多项式的算法.但是这题有一点特殊的地方,每条边必定包含前面30个点的的一个,所以这题可以枚举钱30个点的选和不选的状态,后面的点对应的状态就唯一了.    所以这题就是  dfs+可行性减枝和答案最优减枝. #include<stdio.h> #include<string.h> #include<iostream> #include<string> #include<queue> #i

2018.3.12 np completed problem, vertex cover and traveling salesman problem

1.先是讲了np完全问题的一般概念.简单的说就是一般的计算问题分为p,np和npc问题,还有一类更难的nph问题不过目前不在讨论范围内.npc问题的特点是,所有的np问题都能reduce到npc问题.就比如说我们要解决让刁大大能够从1数到10的问题.虽然这个问题很难,但是我们可以换个思路解决,我们把它推演(reduce)一下,变成教他从1数到20的问题.那么如果我们解决了这个新问题,原来的老问题也就同时解决了.从1数到10和从1数到20,就相当于np问题和npc问题之间的关系. 那么这样的结果就