CodeChef - VRTXCOVR

版权声明:选经典题目,写精品文章. https://blog.csdn.net/nka_kun/article/details/83036120

All submissions for this problem are available.
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 ≤ i ≤ n/2, nodes 2i and 2i - 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, 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

题意:给出一个图,把这些点分别标记0或1,满足第2n和第2n-1个点不同,并且有边相连的两个点不能同时为0,问是否有种方案可以满足.
思路:2-SAT模型,不知道就只能瞎搞了。。
把2n-1和2n看成一组,按照题目给出的边,建边方式如下:
模型一:两者(A,B)不能同时取
  那么选择了A就只能选择B’,选择了B就只能选择A’
  连边A→B’,B→A’

模型二:两者(A,B)不能同时不取
  那么选择了A’就只能选择B,选择了B’就只能选择A
  连边A’→B,B’→A

模型三:两者(A,B)要么都取,要么都不取
  那么选择了A,就只能选择B,选择了B就只能选择A,选择了A’就只能选择B’,选择了B’就只能选择A’
  连边A→B,B→A,A’→B’,B’→A’

模型四:两者(A,A’)必取A
  连边A’→A

扫描二维码关注公众号,回复: 3731041 查看本文章

详见:https://blog.csdn.net/moguxiaozhe/article/details/49047085

所以题目给出的边是模型二:(A,B)不能同时取.
然后按照模板跑一下即可.

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define MAXN 200000
#define MAXM 200000
#define mem(a,b) memset(a,b,sizeof(a))

int n,m;
struct node
{
    int v;
    node *next;
};

node edge[MAXM*2];
node *cnt=&edge[0];
node *adj[MAXN];
node edge2[MAXM*2];
node *cnt2=&edge2[0];
node *adj2[MAXN];
int dfn[MAXN],low[MAXN],dcnt;
int stack[MAXN],top;
int Belong[MAXN],Num[MAXN],opp[MAXN],scc;
int In[MAXN],q[MAXN],col[MAXN];
bool Instack[MAXN],ans[MAXN];

inline void Get_int(int &Ret)
{
    char ch;
    bool flag=false;
    for(;ch=getchar(),ch<'0'||ch>'9';)
        if(ch=='-')
            flag=true;
    for(Ret=ch-'0';ch=getchar(),ch>='0'&&ch<='9';Ret=Ret*10+ch-'0');
    flag&&(Ret=-Ret);
}

inline int Get(int x)
{
    if(x%2)
        return x+1;
    return x-1;
}


inline void Addedge(int u,int v)
{
    node *p=++cnt;
    p->v=v;
    p->next=adj[u];
    adj[u]=p;
}

inline void Addedge2(int u,int v)
{
    node *p=++cnt2;
    p->v=v;
    p->next=adj2[u];
    adj2[u]=p;
}

void Read()
{
    Get_int(n);
    Get_int(m);
    int i,j,k;
    for(int i = 0;i<= n+n;i++)
    {
    	dfn[i]=low[i]= stack[i]=Belong[i] = Num[i] =opp[i] = In[i]= q[i]= col[i]=Instack[i] = ans[i] = 0;
    	adj[i] = adj2[i] = NULL;
    }
    cnt=&edge[0];
    cnt2=&edge2[0];
    for(i=1;i<=m;i++)
    {
        Get_int(j);
        Get_int(k);
        Addedge(Get(j),k);
        Addedge(Get(k),j);
    }
}

void Tarjan(int u)
{
    int v;
    dfn[u]=low[u]=++dcnt;
    stack[++top]=u;
    Instack[u]=true;
    for(node *p=adj[u];p;p=p->next)
    {
        v=p->v;
        if(!dfn[v])
        {
            Tarjan(v);
            low[u]=min(low[u],low[v]);
        }
        else if(Instack[v])
            low[u]=min(low[u],dfn[v]);
    }
    if(dfn[u]==low[u])
    {
        scc++;
        do
        {
            v=stack[top];
            top--;
            Instack[v]=false;
            Belong[v]=scc;
            Num[scc]++;
        }while(v!=u);
    }
}

bool Work()
{
    int i;
    for(i=1;i<=n;i++)
        if(!dfn[i])
            Tarjan(i);
    for(i=1;i<=n;i+= 2)
    {
        if(Belong[i]==Belong[i+1])
            return false;
        opp[Belong[i]]=Belong[i+1];
        opp[Belong[i+1]]=Belong[i];
    }
    int u,v;
    for(i=1;i<=n;i++)
        for(node *p=adj[i];p;p=p->next)
        {
            v=p->v;
            if(Belong[i]!=Belong[v])
            {
                Addedge2(Belong[v],Belong[i]);
                In[Belong[i]]++;
            }
        }
    int l=0,r=0;
    for(i=1;i<=scc;i++)
        if(!In[i])
        {
            q[r]=i;
            r++;
        }
    while(l<r)
    {
        u=q[l];
        l++;
        if(!col[u])
        {
            col[u]=1;
            col[opp[u]]=-1;
        }
        for(node *p=adj2[u];p;p=p->next)
        {
            v=p->v;
            In[v]--;
            if(!In[v])
            {
                q[r]=v;
                r++;
            }
        }
    }
    for(i=1;i<=n;i+= 2)
        if(col[Belong[i]]==1)
            ans[i]=true;
    return true;
}
void Print()
{
    if(Work())
    {
    	printf("possible\n");
        int i;
        for(i=1;i<=n;i+= 2)
        {
        	if(i == n)
        	{
        		printf("1");
        		break;
        	}
        	if(ans[i])
                printf("10");
            else
                printf("01");
        }
        printf("\n");
    }
    else
        printf("impossible\n");
}

int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		dcnt = scc = top = 0;
		
		Read();
    	Print();
	}
	
    return 0;
}

猜你喜欢

转载自blog.csdn.net/nka_kun/article/details/83036120