• 染色法判断二分图


    写的很菜 , 欢迎建议、补充

    二分图的定义

    图G=(V,E),顶点集V可分割为两个互不相交的子集,并且图中每条边依附的两个顶点都分属于这两个互不相交的子集,两个子集内的顶点不相邻。-----百科

    就是当一个东西可以分成两半的时候,你可以问自己一下这满足不满足二分图的性质。

    解释的很草率 ↑    ,   题解里向来都是说 : "显而易见这是二分图", 我也不好这么说 , 题做得还少, 这几天多练练没准就找到手感了 。

    当你定好了解题的方向,那么如何判定这个是二分图呢 。

    染色法 。

    需要两种颜色,我们从任意点开始染色, 把与其相邻的点染成与它相反的颜色 , 整个图染完色之后,如果满足相连的两个点颜色都不同, 那么就可以断定它是二分图了 , 如果发现相连点颜色相同 ,那就满足不了二分图的定义了。  

    这个染色过程通过BFS或者DFS实现。

    下面贴个BFS代码  , DFS同理。

     1 void connect(int x,int y)//拿邻接表存的图,用vector也可以。 
     2 {
     3     pre[++cnt]=last[x];
     4     other[cnt]=y;
     5     last[x]=cnt;
     6 } 
     7 void BFS(int x)
     8 {
     9     queue <int>q;
    10     q.push(x);
    11     color[x]=1;            //BFS染色 
    12     while(!q.empty())
    13     {
    14         int tmp=q.front();
    15         q.pop();
    16         for(int i=last[tmp];i;i=pre[i])
    17         {
    18             int to=other[i];
    19             if(to==tmp)continue;
    20             if(color[to]==color[tmp]){        //发现相邻点的颜色相等,于是这个图不是二分图 
    21                 exit(0);
    22             }
    23             else{
    24                 color[to]=1^color[tmp];        //把相邻点涂成相反的颜色,然后把这个点加入队列 
    25                 q.push(to);
    26             }
    27         }
    28     }
    29 }
    30 int main()
    31 {
    32     memset(color,-1,sizeof(color));
    33     for(int i=1;i<=N;i++)
    34         if(color[i]==-1)BFS(i);                //=、= 
    35 }

    判断二分图的代码就这样↑

     

    下面给道可爱的例题

    NOIP2008  双栈排序 (可以在LuoguP1155提交)

    戳链接https://www.luogu.org/problem/show?pid=1155看题面,就不粘贴了

    这个题就是有一个序列,给你两个栈,通过进栈退栈输出一个排序的序列 

    (按理来说肯定不能纯模拟做,虽然题解里有一个超级长的纯模拟代码)

    联想到二分图,我们应该去思考如何把这些数分成两部分,分别放进两个栈里

    下面我们要考虑怎样的两个元素可以放到一个栈里面,

    显然的 ,当i<j<k , a[k]<a[i]<a[j],i和j是不能放到同一个栈里的 ,于是i,j就可以构成图的两个子集的一条边 

    我们枚举出来所有的i,j 进行连边,

        for(int i=N-1;i>=1;i--)sufmin[i]=min(sufmin[i+1],a[i+1]);
        for(int i=1;i<=N;i++)
            for(int j=i+1;j<=N;j++)
                if(a[i]<a[j]&&a[i]>sufmin[j]){
                connect(i,j);connect(j,i);
            }

    之后利用上面的染色法判定二分图,就可以把所有的数分成两部分,再进行简单的模拟,就可以得到答案了。

    如果不是这个不是二分图,那就说明无解。

     

    先写这么多了,很啰嗦求见谅,学了新的再加内容。

     

  • 相关阅读:
    集合的代数运算
    集合的代数运算
    poj1639 Picnic Planning,K度限制生成树
    C/C++学习站点资源
    Mustache 使用心得总结
    PostgreSQL服务端监听设置及client连接方法
    【线性规划与网络流24题】汽车加油行驶问题 分层图
    linux系统下信号具体解释2
    【数据结构】栈-数组的实现
    EJB究竟是什么,真的那么神奇吗??
  • 原文地址:https://www.cnblogs.com/Elfish/p/7535169.html
Copyright © 2020-2023  润新知