• 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-ans);
        }
        return 0;
    }
    /************
    
    ************/
    View Code
  • 相关阅读:
    [敏杰开发]Beta Scrum Meeting 6
    团队作业第六次--Beta阶段集合随笔
    宅单词——置顶博客
    Beta冲刺总结
    随机组队吐槽
    用户使用调查报告
    Beta冲刺--Day7
    Beta冲刺--Day6
    Beta冲刺--Day5
    Beta冲刺--Day4
  • 原文地址:https://www.cnblogs.com/acjiumeng/p/7747265.html
Copyright © 2020-2023  润新知