poj2942 点-双联通+二分图染色

Posted walfy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了poj2942 点-双联通+二分图染色相关的知识,希望对你有一定的参考价值。

题意:有一群骑士要坐在一个圆形的桌子上,他们之间有些人相互讨厌,所以不能挨着,要求算出一次也不能坐在桌子上的人,每次会议桌子必须奇数个人,一个人不能开会

题解:可以先建一个补图,要满足题目条件我们只要找出所有奇圈(奇数个点的环),求出点-双联通分量,对于每一个单独的点-双连通分量,如果它一定是一个奇圈,那么不能够通过二分图染色,可以通过画图验证这条结论,那么我们对于所有的奇圈里的点进行染色,最后输出没有染色过的点,因为有可能会出现多次染色的点,所以不能直接每次加点数

坑点:不能用stl,tle了好多发,最后把所有的vector,map都换成了数组就过了,不能用vector存图,那么就用我最喜欢的链式前向星吧= = 

技术分享
#include<map>
#include<set>
#include<list>
#include<cmath>
#include<queue>
#include<stack>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pii pair<int,int>
#define C 0.5772156649
#define pi acos(-1.0)
#define ll long long
#define mod 1000000007
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1

using namespace std;
using namespace __gnu_cxx;

const double g=10.0,eps=1e-7;
const int N=1000+10,maxn=1000000+10,inf=0x3f3f3f;

struct edge{
    int to,Next;
}e[maxn];
int bcc[N];
int index,num;
int cnt,head[N];
int dfn[N],low[N];
int bccno[N];
struct ewedge{int from,to;};
stack<ewedge>s;
bool ma[N][N];
int in[N],ok[N];
int color[N];
bool notsub;
void add(int x,int y)
{
    e[cnt].to=y;
    e[cnt].Next=head[x];
    head[x]=cnt++;
    e[cnt].to=x;
    e[cnt].Next=head[y];
    head[y]=cnt++;
}
void dfs(int u,int f,int p)
{
    if(notsub)return ;
    color[u]=p;
    int c=3-p;
    for(int i=head[u];~i;i=e[i].Next)
    {
        int x=e[i].to;
        if(ok[x])
        {
            if(!color[x])dfs(x,u,c);
            else
            {
                if(color[x]!=c)notsub=1;
            }
        }
    }
}
void tarjan(int u,int f)
{
    low[u]=dfn[u]=++index;
    for(int i=head[u];~i;i=e[i].Next)
    {
        int x=e[i].to;
        ewedge e=(ewedge){u,x};
        if(x==f)continue;
        if(!dfn[x])
        {
            s.push(e);
            tarjan(x,u);
            low[u]=min(low[u],low[x]);
            if(low[x]>=dfn[u])
            {
                int res=0;
                num++;
                memset(ok,0,sizeof ok);
                int be=0;
                for(;;)
                {
                    ewedge p=s.top();s.pop();
                    if(bccno[p.from]!=num)
                    {
                        bcc[res++]=p.from;
                        be=p.from;
                        bccno[p.from]=num;
                        ok[p.from]=1;
                    }
                    if(bccno[p.to]!=num)
                    {
                        bcc[res++]=p.to;
                        be=p.to;
                        bccno[p.to]=num;
                        ok[p.to]=1;
                    }
                    if(p.from==e.from&&p.to==e.to)break;
                }
                //判断是不是二分图
                for(int i=0;i<res;i++)
                    color[bcc[i]]=0;
                notsub=0;
                dfs(be,-1,1);
                if(notsub)
                {
                    for(int i=0;i<res;i++)
                        in[bcc[i]]=1;
                }
              /*  cout<<notsub<<"--------";
                for(int j=0;j<bcc.size();j++)
                    cout<<bcc[j]<<" ";
                cout<<endl;*/
            }
        }
        else
        {
            if(dfn[x]<dfn[u])low[u]=min(low[u],dfn[x]);
        }
    }
}
void init(int n)
{
    memset(head,-1,sizeof head);
    memset(ma,0,sizeof ma);
    for(int i=1;i<=n;i++)
    {
        bccno[i]=dfn[i]=low[i]=in[i]=0;
    }
    while(!s.empty())s.pop();
    index=num=cnt=0;
}
int main()
{
    int n,m;
    while(~scanf("%d%d",&n,&m))
    {
        if(!n&&!m)break;
        init(n);
        while(m--)
        {
            int a,b;
            scanf("%d%d",&a,&b);
            ma[a][b]=ma[b][a]=1;
        }
        for(int i=1;i<=n;i++)
            for(int j=i+1;j<=n;j++)
                if(!ma[i][j])
                    add(i,j);
        for(int i=1;i<=n;i++)
            if(!dfn[i])
                tarjan(i,-1);
        int ans=0;
        for(int i=1;i<=n;i++)
            if(in[i])
                ans++;
        printf("%d\n",n-ans);
    }
    return 0;
}
/************

************/
View Code

 

以上是关于poj2942 点-双联通+二分图染色的主要内容,如果未能解决你的问题,请参考以下文章

POJ 2942

POJ2942 Knights of the Round Table[点双连通分量|二分图染色|补图]

POJ 2942Knights of the Round Table(双联通分量+染色判奇环)

poj2942 Knights of the Round Table

POJ 2942Knights of the Round Table(二分图判定+双连通分量)

POJ2942 Knights of the Round Table 点双连通分量,逆图,奇圈