赞
踩
这道题可以说是二分图的极致运用了;
两个栈来实现元素的排序,首先要能推出 a[j]>a[i],a[k]<a[i] (i<j<k),这样的a[i]和a[j]是不能放在一个栈里面的,必须放在不同的栈里才能实现排序;
知道了这个,我们就可以找出序列里所有的这几对元素,把它们连起来,看是否是一个二分图,也就是说看它们是否可以分为两个栈;这道题也就写完了;
判定二分图用染色法不要多说,还有一个要注意细节就是建边,也就是说把序列里的那几对元素都找出来,一般复杂度为O(n^3) ,有个小技巧就是a[k]可以用一个数组b[i]表示,b[i]数组的意义就是(i–n)的所有元素的最小值;,这样复杂度可以降为O(n^2);
最后只要根据染的颜色把对应的步骤输出来就行;
代码:
#include<bits/stdc++.h> #define LL long long #define pa pair<int,int> #define lson k<<1 #define rson k<<1|1 //ios::sync_with_stdio(false); using namespace std; const int N=1100; const int M=100100; const LL mod=1e9+7; struct Node{ int to,nex; }edge[M]; int head[N]; int cnt; void add(int p,int q){ edge[cnt].to=q; edge[cnt].nex=head[p]; head[p]=cnt++; } int a[N]; int b[N]; int color[N]; bool dfs(int p,int q){ color[p]=q; for(int i=head[p];~i;i=edge[i].nex){ int v=edge[i].to; if(!color[v]){ if(!dfs(v,3-q)) return false; } else if(color[v]==q) return false; } return true; } stack<int>s1,s2; int main(){ ios::sync_with_stdio(false); memset(head,-1,sizeof(head)); int n; cin>>n; b[n+1]=2e9;//边界条件 for(int i=1;i<=n;i++) cin>>a[i]; for(int i=n;i>=1;i--) b[i]=min(b[i+1],a[i]); for(int i=1;i<=n-2;i++){ for(int j=i+1;j<=n-1;j++){ if(a[j]>a[i]&&b[j+1]<a[i]){ add(i,j);add(j,i);//建边 } } } for(int i=1;i<=n;i++){ if(!color[i]){ if(!dfs(i,1)){ cout<<0<<endl;//染色失败 return 0; } } } int ans=1; for(int i=1;i<=n;i++){ if(color[i]==1){//进入栈s1 s1.push(a[i]); cout<<"a "; } else{//进入栈s2 s2.push(a[i]); cout<<"c "; } while((!s1.empty()&&s1.top()==ans)||(!s2.empty()&&s2.top()==ans)){ if(!s1.empty()){ if(s1.top()==ans){ cout<<"b "; ans++; s1.pop(); } } if(!s2.empty()){ if(s2.top()==ans){ cout<<"d "; ans++; s2.pop(); } } } } return 0; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。