二分图 and code1170 双栈排序
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 双栈排序的更多相关文章
- 洛谷——P1155 双栈排序
题目描述 Tom最近在研究一个有趣的排序问题.如图所示,通过2个栈S1和S2,Tom希望借助以下4种操作实现将输入序列升序排序. 操作a 如果输入序列不为空,将第一个元素压入栈S1 操作b 如果栈S1 ...
- NOIP2008双栈排序[二分图染色|栈|DP]
题目描述 Tom最近在研究一个有趣的排序问题.如图所示,通过2个栈S1和S2,Tom希望借助以下4种操作实现将输入序列升序排序. 操作a 如果输入序列不为空,将第一个元素压入栈S1 操作b 如果栈S1 ...
- [NOIP2008]双栈排序 【二分图 + 模拟】
题目描述 Tom最近在研究一个有趣的排序问题.如图所示,通过2个栈S1和S2,Tom希望借助以下4种操作实现将输入序列升序排序. 操作a 如果输入序列不为空,将第一个元素压入栈S1 操作b 如果栈S1 ...
- Luogu1155 NOIP2008 双栈排序 【二分图染色】【模拟】
Luogu1155 NOIP2008 双栈排序 题目描述 Tom最近在研究一个有趣的排序问题.如图所示,通过 2个栈 S1 和 S2 ,Tom希望借助以下 44 种操作实现将输入序列升序排序. 操作 ...
- 虚拟化构建二分图(BZOJ2080 题解+浅谈几道双栈排序思想的题)
虚拟化构建二分图 ------BZOJ2080 题解+浅谈几道双栈排序思想的题 本题的题解在最下面↓↓↓ 不得不说,第一次接触类似于双栈排序的这种题,是在BZOJ的五月月赛上. [BZOJ4881][ ...
- 双栈排序 2008年NOIP全国联赛提高组(二分图染色)
双栈排序 2008年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 大师 Master 题目描述 Description Tom最近在研究一个有 ...
- P1155 双栈排序(二分图染色)
P1155 双栈排序(二分图染色) 题目描述 Tom最近在研究一个有趣的排序问题.如图所示,通过2个栈S1和S2,Tom希望借助以下4种操作实现将输入序列升序排序. 操作a 如果输入序列不为空,将第一 ...
- [luogu1155 NOIP2008] 双栈排序 (二分图染色)
传送门 Description Input 第一行是一个整数 n . 第二行有 n 个用空格隔开的正整数,构成一个 1−n 的排列. Output 共一行,如果输入的排列不是"可双栈排序排列 ...
- [LuoguP1155]双栈排序_二分图_bfs
双栈排序 题目链接:https://www.luogu.org/problem/P1155 数据范围:略. 题解: 神仙题. 就第一步就够劝退了. 这个二分图非常不容易,首先只有两个栈,不是属于一个就 ...
随机推荐
- I.MX6 linux kernel编译错误处理
/******************************************************************************** * I.MX6 linux kern ...
- 深入__proto__和prototype的区别和联系
前话 有一个一个装逼的同事,写了一段代码 function a(){} a.__proto__.__proto__.__proto__ 然后问我,下面这个玩意a.__proto__.__proto__ ...
- MemSQL start[c]up Round 1 B题
题目链接 http://codeforces.com/contest/325/problem/B 第一遍写了暴搜,果断TLE 然后上了二分,结果120组数据只有第40组过不了,我就写了奇怪的东西... ...
- salesforce linghtning component 自动添加标准style css样式
Your app automatically gets Lightning Design System styles if it extends force:slds <aura:applic ...
- CH1807 Necklace
题意 背景 有一天,袁☆同学绵了一条价值连城宝石项链,但是,一个严重的问题是,他竟然忘记了项链的主人是谁!在得知此事后,很多人向☆同学发来了很多邮件,都说项链是自己的,要求他归还(显然其中最多只有一个 ...
- test20181020 B君的第一题
题意 分析 二次剩余问题. x,y相当于二次方程 \[ x^2-bx+c=0 \mod{p} \] 的两根. 摸意义下的二次方程仍然考虑判别式\(\Delta=b^2-4c\). 它能开根的条件是\( ...
- Archiva与maven配置使用
在之前的博文里头已经介绍了Archiva私服的使用,本文主要介绍,如何与maven进行配置,在进行maven使用的时候可以自动上传至Archiva上 1.设置maven的用户配置,到maven的安装目 ...
- hadoop之 Hadoop1.x和Hadoop2.x构成对比
Hadoop1.x构成: HDFS.MapReduce(资源管理和任务调度):运行时环境为JobTracker和TaskTracker: Hadoop2.0构成:HDFS.MapReduce/其他 ...
- Linux进程间通信——使用信号量(转)
这篇文章将讲述别一种进程间通信的机制——信号量.注意请不要把它与之前所说的信号混淆起来,信号与信号量是不同的两种事物.有关信号的更多内容,可以阅读我的另一篇文章:Linux进程间通信——使用信号.下面 ...
- win2008以上的系统,在vmware esxi5.5里怎么使用自定义规范管理器?sysprep
经过测试,原来08以上的系统自带了sysprep.exe,所以vcenter对08以上的系统直接使用自定义规范管理器即可,跟linux一样了.注意不要跟03一样写入了sn即可. vCenter可使用s ...