6.6二分图

二分图是这样一个图: 有两顶点集且图中每条边的的两个顶点分别位于两个顶点集中,每个顶点集中没有边直接相连接。

无向图G为二分图的充分必要条件是,G至少有两个顶点,且其所有回路的长度均为偶数。

判断二分图的常见方法是染色法: 开始对任意一未染色的顶点染色,之后判断其相邻的顶点中,若未染色则将其染上和相邻顶点不同的颜色, 若已经染色且颜色和相邻顶点的颜色相同则说明不是二分图,若颜色不同则继续判断,bfs和dfs都可以。

易知:任何无回路的的图均是二分图。

代码:

bool Color(int u)

{

for(int i=head[u]; ~i; i=edge[i].next)

{

int v = edge[i].to;

if(!col[v])

{

col[v] = !col[u];

if(!Color(v)) return false;

}

else if(col[v] == col[u])

return false;

}

return true;

}

Codevs1170 双栈排序NOIP2008

题目分析:

分析条件,我们把问题抽象为数学模型。设输入序列为S,考虑S[i],S[j]两个元素不能进入同一个栈的条件.注意,这里所说的"S[i],S[j]两个元素不能进入同一个栈",不是说仅仅不能同时在一个栈中,而是自始至终不能进入一个栈,即如果有解,那么S[i],S[j]一定进入过的栈不同.

结论P: S[i],S[j]两个元素不能进入同一个栈 <=> 存在k,满足i<j<k,使得S[k]<S[i]<S[j]. 证明略过,请参考sqybi.尝试后可以发现结论P是正确的.

把每个元素按照输入序列中的顺序编号,看作一个图中的每个顶点.这时,我们对所有的(i,j)满足i<j,判断是否满足结论P,即S[i],S[j]两个元素能否进入同一个栈.如果满足P,则在i,j之间连接一条边.

我们对图染色,由于只有两个栈,我们得到的图必须是二分图才能满足条件.由于要求字典序最小,即尽量要进入栈1,我们按编号递增的顺序从每个未染色的顶点开始染色,相邻的顶点染上不同的色,如果发生冲突,则是无解的.否则我们可以得到每个顶点颜色,即应该进入的栈.

接下来就是输出序列了,知道了每个元素的决策,直接模拟了.

在判断数对(i,j)是否满足P时,枚举检查是否存在k的时间复杂度是O(n),则总的时间复杂度是O(n^3),对于n=1000是太大了.这原因在于过多得枚举了k,我们可以用动态规划把枚举k变为O(1)的算法.

设F[i]为Min{S[i],S[i+1],S[i+2]..S[n-1],S[n]},状态转移方程为F[i]=Min{ S[i] , F[i+1] }.边界为F[N+1]=极大的值.

判断数对(i,j)是否满足P,只需判断(S[i]<S[j] 并且 F[j+1]<S[i])即可.时间复杂度为O(n^2).

多亏有题解,不然根本想不出来那个结论P啊...

模拟也是个问题:

知道了每个点的color(cc),入栈很容易。问题是什么时候出栈。

设a为当前需要出栈的元素,b为a+1

当s1的栈顶是a时,立刻出栈。因为出s1的优先级是2,只有入s1比它高,但那样就把应该出的元素压住了,显然不行。所以直接出就能保证字典序最小。

当s2的栈顶是a时,麻烦来了。因为出s2的优先级比入s1低,所以如果可能应当先入s1,把该出的元素放在s2不管它,直到迫不得已必须出的时候。

  s2出栈的情况:s2的栈顶是a时,cc[i+1]==2 || (cc[i+1]==1&&!s1.empty()&&s1.top()==b) || s1.empty()

注意模拟之前先cc[n+1]=2,保证入栈全部完成时s2不再受入栈限制(cc[i+1]==2)

详见代码:

#include<iostream>
#include<stack>
using namespace std;
const int Size=; int n,data[Size];
int f[Size];
int cc[Size];
bool flag=true;
int a=,b=;
stack<int> s1,s2;
//edge
struct E{
int to;
E *next;
}*head[Size];
void add(int a,int b){
E *p=new E;
p->to=b; p->next=head[a];
head[a]=p;
} void color(int u){
for(E* i=head[u]; i!=NULL; i=i->next){
int v = i->to;
if(!cc[v]){
cc[v] = cc[u]==?:;
color(v);
if(!flag)return;
}
else if(cc[v] == cc[u]){
flag=false;
return;
}
}
} void out(int i){
bool ok=true;
while(ok){
ok=false;
if(!s1.empty()&&s1.top()==a){
s1.pop(); cout<<"b "; a++;b++; ok=true;
}
if(!s2.empty()&&s2.top()==a){
if(cc[i+]==||(cc[i+]==&&!s1.empty()&&s1.top()==b)||s1.empty()){
s2.pop(); cout<<"d "; a++;b++; ok=true;
}
}
}
} int main(){
cin>>n;
for(int i=;i<=n;i++)head[i]=NULL;
for(int i=;i<=n;i++){
cin>>data[i];
}
f[n+]=0x3f3f3f3f;
for(int i=n;i>=;i--){
f[i]=min(data[i],f[i+]);
} for(int i=;i<=n;i++){
for(int j=i+;j<=n;j++){
if(data[i]<data[j]&&f[j+]<data[i]){
add(i,j); add(j,i);
}
}
} for(int i=;i<=n;i++){
if(cc[i]==){
cc[i]=;
color(i);
if(!flag)break;
}
} cc[n+]=;
if(flag){
for(int i=;i<=n;i++){
if(cc[i]==)s1.push(data[i]),cout<<"a ";
else s2.push(data[i]),cout<<"c ";
out(i);
}
}
else cout<<; return ;
}

二分图 and code1170 双栈排序的更多相关文章

  1. 洛谷——P1155 双栈排序

    题目描述 Tom最近在研究一个有趣的排序问题.如图所示,通过2个栈S1和S2,Tom希望借助以下4种操作实现将输入序列升序排序. 操作a 如果输入序列不为空,将第一个元素压入栈S1 操作b 如果栈S1 ...

  2. NOIP2008双栈排序[二分图染色|栈|DP]

    题目描述 Tom最近在研究一个有趣的排序问题.如图所示,通过2个栈S1和S2,Tom希望借助以下4种操作实现将输入序列升序排序. 操作a 如果输入序列不为空,将第一个元素压入栈S1 操作b 如果栈S1 ...

  3. [NOIP2008]双栈排序 【二分图 + 模拟】

    题目描述 Tom最近在研究一个有趣的排序问题.如图所示,通过2个栈S1和S2,Tom希望借助以下4种操作实现将输入序列升序排序. 操作a 如果输入序列不为空,将第一个元素压入栈S1 操作b 如果栈S1 ...

  4. Luogu1155 NOIP2008 双栈排序 【二分图染色】【模拟】

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

  5. 虚拟化构建二分图(BZOJ2080 题解+浅谈几道双栈排序思想的题)

    虚拟化构建二分图 ------BZOJ2080 题解+浅谈几道双栈排序思想的题 本题的题解在最下面↓↓↓ 不得不说,第一次接触类似于双栈排序的这种题,是在BZOJ的五月月赛上. [BZOJ4881][ ...

  6. 双栈排序 2008年NOIP全国联赛提高组(二分图染色)

    双栈排序 2008年NOIP全国联赛提高组  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 大师 Master     题目描述 Description Tom最近在研究一个有 ...

  7. P1155 双栈排序(二分图染色)

    P1155 双栈排序(二分图染色) 题目描述 Tom最近在研究一个有趣的排序问题.如图所示,通过2个栈S1和S2,Tom希望借助以下4种操作实现将输入序列升序排序. 操作a 如果输入序列不为空,将第一 ...

  8. [luogu1155 NOIP2008] 双栈排序 (二分图染色)

    传送门 Description Input 第一行是一个整数 n . 第二行有 n 个用空格隔开的正整数,构成一个 1−n 的排列. Output 共一行,如果输入的排列不是"可双栈排序排列 ...

  9. [LuoguP1155]双栈排序_二分图_bfs

    双栈排序 题目链接:https://www.luogu.org/problem/P1155 数据范围:略. 题解: 神仙题. 就第一步就够劝退了. 这个二分图非常不容易,首先只有两个栈,不是属于一个就 ...

随机推荐

  1. Java---SSH(MVC)面试

    Java---SSH(MVC) 1.        谈谈你mvc的理解 MVC是Model—View—Controler的简称.即模型—视图—控制器.MVC是一种设计模式,它强制性的把应用程序的输入. ...

  2. 浅谈SQL Server---1

    浅谈SQL Server优化要点 https://www.cnblogs.com/wangjiming/p/10123887.html 1.SQL Server 体系结构由哪几部分组成? 2.SQL ...

  3. 6-1 Deque(25 分)Data Structures and Algorithms (English)

    A "deque" is a data structure consisting of a list of items, on which the following operat ...

  4. [UOJ46][清华集训2014]玄学

    uoj description 给出\(n\)个变换,第\(i\)个变换是将区间中\(l_i,r_i\)的数\(x\)变成\((a_ix+b_i)\mod m\). 每次会新增一个变换,或者查询询问如 ...

  5. emacs之自动完成括号

    网上抄来的问题不少,看emacswiki,用autopairs即可 emacsConfig/autopair-setting.el (require 'autopair) (autopair-glob ...

  6. CodeForces - 983B XOR-pyramid(区间dp,异或)

    XOR-pyramid time limit per test 2 seconds memory limit per test 512 megabytes input standard input o ...

  7. UI“三重天”之Selenium(一)

    关注一下UI自动化,记一记笔记. UI自动化的优缺点: 关于UI自动化的优缺点想来大家都有了解,优点:解放人力(并不是完全解放),用机器(涵盖工具.脚本等)代替人工完成测试工作,将测试用例转化为脚本实 ...

  8. ES6系列_5之数字操作

    下面是针对ES6新增的一些数字操作方法进行简单梳理. 1.数字判断和转换 (1)数字验证Number.isFinite( xx ) 使用Number.isFinite( )来进行数字验证,只要是数字, ...

  9. spring jpa sqls

    package com.example.repository; import java.util.List; import org.springframework.data.jpa.repositor ...

  10. delphi加密算法

    function EncryptKey(sUser,sPasswd:string):string;stdcall; var __i,__k,__a : Integer; __s : string; b ...