• 算法复习——二分图染色(洛谷1155)


    题目:

    Tom最近在研究一个有趣的排序问题。如图所示,通过2个栈S1和S2,Tom希望借助以下4种操作实现将输入序列升序排序。

    操作a

    如果输入序列不为空,将第一个元素压入栈S1

    操作b

    如果栈S1不为空,将S1栈顶元素弹出至输出序列

    操作c

    如果输入序列不为空,将第一个元素压入栈S2

    操作d

    如果栈S2不为空,将S2栈顶元素弹出至输出序列

    如果一个1~n的排列P可以通过一系列操作使得输出序列为1,2,…,(n-1),n,Tom就称P是一个“可双栈排序排列”。例如(1,3,2,4)就是一个“可双栈排序序列”,而(2,3,4,1)不是。下图描述了一个将(1,3,2,4)排序的操作序列:<a,c,c,b,a,d,d,b>

    当然,这样的操作序列有可能有几个,对于上例(1,3,2,4),<a,c,c,b,a,d,d,b>是另外一个可行的操作序列。Tom希望知道其中字典序最小的操作序列是什么。

    输入输出格式

    输入格式:

    输入文件twostack.in的第一行是一个整数n。

    第二行有n个用空格隔开的正整数,构成一个1~n的排列。

    输出格式:

    输出文件twostack.out共一行,如果输入的排列不是“可双栈排序排列”,输出数字0;否则输出字典序最小的操作序列,每两个操作之间用空格隔开,行尾没有空格。

    输入输出样例

    输入样例#1:
    【输入样例1】
    4
    1 3 2 4
    【输入样例2】
    4
    2 3 4 1
    【输入样例3】
    3
    2 3 1
    
    
    输出样例#1:
    【输出样例1】
    a b a a b b a b
    【输出样例2】
    0
    【输出样例3】
    a c a b b d

    说明

    30%的数据满足: n<=10

    50%的数据满足: n<=50

    100%的数据满足: n<=1000

    题解:

    首先这道题一来是比较难看出是二分图染色的·····

    但想一想···这道题用策略模拟,不是数据结构题,也不是dp题,更别提数论题···那还能是什么呢···只有图论题了···

    而且看到到双栈就可以考虑二分图染色了······通过两个点是否在同一栈的逻辑关系来建图(好牵强的理由,我反正想不出)····、

    以下是洛谷官方题解:

    1.首先考虑一个简单情况——单栈排序,显然有这样的一个事实:

    a[i]和a[j] 不能压入同一个栈⇔存在一个k,使得i<j<k且a[k]<a[i]<a[j]

    时间复杂度为O(n^3).对于n<=1000仍显吃力,对此可以用动态规划的思想,将上述复杂度降到O(n^2)。

    状态:f[i]=min(a[i],a[i+1], ... ,a[n])

    边界条件:f[n+1]=INF;

    状态转移方程:f[i]=min(f[i+1],a[i]);

    于是上述判断就转化为了f[j+1]<a[i] && a[i]<a[j]

    2.扩展到双栈排序:

    如果a[i]和a[j]不能在一个栈内,即连接一条i与j之间的无向边,接下来我们只需要判断这个图是否为二分图

    由于题目中说编号的字典序要尽可能的小,那么就把编号小的尽可能放到stack1

    判断二分图的方法可以采用黑白染色的方式,先从编号小的开始染,第一个顶点染成黑色,相邻的顶点染成不同的颜色,如果发现黑白冲突,那么说明这个图不是一个二分图,是不合法的,输出0.

    (DFS或BFS染色均可)

    3.染色后所有黑色的点进stack1,所有白色的点进stack2,最后模拟输出过程就可以了.

    代码:

    一定注意用stack结构在调用top函数前一定要判断栈是否为空,不然要报错······

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cmath>
    #include<cctype>
    #include<cstring>
    #include<string>
    #include<algorithm>
    #include<ctime>
    #include<stack>
    using namespace std;
    stack<int>sta1;
    stack<int>sta2;
    const int N=1005;
    const int M=1000005;
    int minn[N];
    int n,num[N],color[N];
    int fst[N],nxt[M*2],go[M*2],tot=0;
    inline void comb(int a,int b)
    {
      nxt[++tot]=fst[a],fst[a]=tot,go[tot]=b;
    }
    inline void dfs(int u,int fa)
    {
      for(int e=fst[u];e;e=nxt[e])
      {
        int v=go[e];
        if(v==fa)  continue;
        if(!color[v])
        {
          color[v]=(color[u]==1?2:1);
          dfs(v,u);
        }
        else
        {
          if(color[u]==color[v])  
          {
            cout<<"0"<<endl;
            exit(0);
          }
        }
      }
    }
    int main()
    {
      //freopen("a.in","r",stdin);
      scanf("%d",&n);
      for(int i=1;i<=n;i++)
        scanf("%d",&num[i]);
      minn[n]=num[n];
      for(int i=n-1;i>=1;i--)
        minn[i]=min(num[i],minn[i+1]);
      for(int i=1;i<n-1;i++)
        for(int j=i+1;j<n;j++)
          if(num[i]<num[j]&&minn[j+1]<num[i])
            comb(i,j),comb(j,i);
      for(int i=1;i<=n;i++)        
        if(!color[i])
        {
          color[i]=1;
          dfs(i,0);
        }
      int cnt=1;
      for(int i=1;i<=n;i++)
      {
        if(color[i]==1)
        {  
          sta1.push(num[i]);
          cout<<"a"<<" ";
        }
        else
        {  
          sta2.push(num[i]);
          cout<<"c"<<" ";
        }
        while((!sta1.empty()&&sta1.top()==cnt)||(!sta2.empty()&&sta2.top()==cnt))
        {
          if(!sta1.empty()&&sta1.top()==cnt)
          {
            sta1.pop();
            cout<<"b"<<" ";
          }
          else
          {
            sta2.pop();
            cout<<"d"<<" ";
          }
          cnt++;
        }
      }
      return 0;
    }

         

  • 相关阅读:
    Microsoft Enterprise Library 5.0 系列(二) Cryptography Application Block (初级)
    Microsoft Enterprise Library 5.0 系列(五) Data Access Application Block
    Microsoft Enterprise Library 5.0 系列(八) Unity Dependency Injection and Interception
    Microsoft Enterprise Library 5.0 系列(九) Policy Injection Application Block
    Microsoft Enterprise Library 5.0 系列(三) Validation Application Block (高级)
    软件研发打油诗祝大家节日快乐
    从挖井的故事中想到开发管理中最容易忽视的几个简单道理
    ITIL管理思想的执行工具发布
    管理类软件设计“渔”之演化
    20070926日下午工作流与ITILQQ群 事件管理 讨论聊天记录
  • 原文地址:https://www.cnblogs.com/AseanA/p/7474055.html
Copyright © 2020-2023  润新知