1. 程式人生 > >Vertex Cover CodeChef

Vertex Cover CodeChef

You are given an undirected graph G = (V, E) containing N nodes and M edges. The nodes are numbered from 1 to N. A subset C of V is a vertex cover if for every edge (u, v) ∈ E, at least one of u and v belong to C. Note that C = V is always a vertex cover.

Consider a partition of V into two sets A and B

. It is said to be a valid partition, if the following two conditions are satisfied: A should be a vertex cover. And for each i such that 1 ≤ in/2, nodes 2*i and 2*i - 1 don't belong to the same set (i.e. one belongs to set A and the other to set B).

Determine if a valid partition exists. If it exists, provide an example of one valid

partition.

Input

  • The first line of the input contains a single integer T denoting the number of test cases. The description of T test cases follows.
  • The first line of each test case contains two space-separated integers N and M denoting the number of nodes and number of edges in the graph respectively.
  • Each of the following M lines contains two space-separated integers u and v denoting an edge between nodes u and v.

Output

  • For each test case, print a line containing the string "possible" (without quotes) if a solution exists or "impossible" otherwise.
  • If a solution exists, print a second line containing a binary string. The i-th character of this string should be '0' if vertex i is in set B or '1' if it is in set A.

Constraints

  • 1 ≤ T ≤ 105
  • 1 ≤ N ≤ 2 · 105
  • 0 ≤ M ≤ 2 · 105
  • 1 ≤ u, vN
  • 1 ≤ sum of N over all test cases ≤ 106
  • 1 ≤ sum of M over all test cases ≤ 106

Example

Input:

2
3 2
1 2
2 3
4 5
1 3
2 4
1 4 
1 2
2 3

Output:

possible
011
impossible

Explanation

Example case 1: We can put nodes numbered 2 and 3 in set A and node 1 in set B. Note that this is a valid partition because set A is a vertex cover; also, nodes numbered 1 and 2 belong to different sets.

Example case 2: There exists no partition which satisfies the conditions.

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;

#define rep(i,a,b) for(int i=a;i<b;++i)
#define per(i,a,b) for(int i=b-1;i>=a;--i)

const int N=4e5+10;
const int M=4e6+10;

struct Edge{
	int u,v,nt;
	Edge(int _u=0,int _v=0,int _nt=0):u(_u),v(_v),nt(_nt){}
}edge[M];
int head[N],tot;
void add_edge(int u,int v){
	edge[tot]=Edge(u,v,head[u]);
	head[u]=tot++;
}

int low[N],dfn[N],Stack[N],Belong[N];
int Index,top;
int scc;
bool Instack[N];
int num[N];
void Tarjan(int u){
	low[u]=dfn[u]=++Index;
	Stack[top++]=u;
	Instack[u]=true;
	for(int i=head[u];i!=-1;i=edge[i].nt){
			Edge& e=edge[i];
			if(!dfn[e.v]){
				Tarjan(e.v);
				low[u]=min(low[u],low[e.v]);
			}
			else if(Instack[e.v])
				low[u]=min(low[u],dfn[e.v]);
	}
	if(low[u]==dfn[u]){
		scc++;
		int v=u;
		do{
			v=Stack[--top];
			Instack[v]=false;
			Belong[v]=scc;
			num[scc]++;
		}while(v!=u);
	}
}

bool solvable(int n){
	fill(dfn,dfn+2*n+1,0);
	fill(Instack,Instack+2*n+1,0);
	fill(num,num+2*n+1,0);
	//memset(dfn,0,sizeof(dfn));
	//memset(Instack,false,sizeof(Instack));
	//memset(num,0,sizeof(num));
	Index=scc=top=0;
	for(int i=1;i<=2*n;i++)
		if(!dfn[i])Tarjan(i);
	for(int i=1;i<=n;i++){
		if(Belong[i]==Belong[i+n])return false;
	}
	return true;
}

queue<int> q1,q2;
vector<vector<int> > dag;
int color[N];
int indeg[N],cf[N];

void solve(int n){
	dag.assign(scc+1,vector<int>());
	fill(indeg,indeg+2*n+1,0);
	fill(color,color+2*n+1,-1);
	//memset(indeg,0,sizeof(indeg));
	//memset(color,0,sizeof(color));
	for(int u=1;u<=2*n;u++){
		for(int i=head[u];i!=-1;i=edge[i].nt){
			Edge& e=edge[i];
			if(Belong[u]!=Belong[e.v]){
				dag[Belong[e.v]].push_back(Belong[u]);
				indeg[Belong[u]]++;
			}
		}
	}

	for(int i=1;i<=n;i++){//標記對立點,同一個集合裡面的兩個點 對應的塊是互斥的 
		int a=i,b=i+n;
		cf[Belong[a]]=Belong[b];
		cf[Belong[b]]=Belong[a];
	}

	while(!q1.empty())q1.pop();
	while(!q2.empty())q2.pop();
	for(int i=1;i<=scc;i++){
		if(indeg[i]==0)q1.push(i);
	}
	while(!q1.empty()){
		int u=q1.front();
		q1.pop();
		if(color[u]==-1){
			color[u]=1;
			color[cf[u]]=0;
		}
		int sz=dag[u].size();
		for(int i=0;i<sz;i++){
			indeg[dag[u][i]]--;
			if(indeg[dag[u][i]]==0)
				q1.push(dag[u][i]);
		}
	}
}


int main(){
	int T;
	scanf("%d",&T);
	while(T--){
		int n,m;
		scanf("%d %d",&n,&m);

		tot=0;
		fill(head,head+2*n+1,-1);

		rep(i,0,m){
			int u,v;
			scanf("%d %d",&u,&v);
			add_edge(u+n,v);
			add_edge(v+n,u);
		}
		for(int i=1;i+i<=n;i++){
			int a=(i<<1)-1,b=i<<1;
			//printf("a:%d b:%d\n",a,b);
			add_edge(a,b+n);
			add_edge(b,a+n);
			add_edge(a+n,b);
			add_edge(b+n,a);
		}

		if(solvable(n)){
			printf("possible\n");
			solve(n);
			for(int i=1;i<=n;i++){
				if(color[Belong[i]])putchar('1');
				else putchar('0');
			}
			putchar('\n');
		}else{
			printf("impossible\n");
		}
	}
	return 0;
}