Vertex Cover CodeChef
阿新 • • 發佈:2018-12-14
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
Determine if a valid partition exists. If it exists, provide an example of one valid
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, v ≤ N
- 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;
}