zoukankan      html  css  js  c++  java
  • 染色法判断二分图

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

    二分图的定义

    图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);
            }

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

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

     

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

     

  • 相关阅读:
    RUST实践.md
    redis.md
    opencvrust.md
    aws rds can't connect to mysql server on 'xx'
    Foundation ActionScript 3.0 With Flash CS3 And Flex
    Foundation Flash Applications for Mobile Devices
    Flash Mobile Developing Android and iOS Applications
    Flash Game Development by Example
    Actionscript 3.0 迁移指南
    在SWT中非UI线程控制界面
  • 原文地址:https://www.cnblogs.com/Elfish/p/7535169.html
Copyright © 2011-2022 走看看