博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
loj #6136. 「2017 山东三轮集训 Day4」Left
阅读量:5294 次
发布时间:2019-06-14

本文共 4310 字,大约阅读时间需要 14 分钟。

题目:

1055088-20170707161325894-115966358.png

题解:

我们可以发现所有的交换器都是一个位置连接着下一层左侧的排序网络,另一个位置连着另一侧的排序网络。

而下一层是由两个更低阶的排序网络构成的。
两个网络互不干扰。所以我们可以通过第一行和最后一行列出多个2-SAT的约束限制。
所以我们可以在每一次都跑一边2-SAT来决策出最外层的交换器是否开启。
然后我们就可以发现每次2-SAT都一定有解,也就是说不可能出现无解的情况。
用2-SAT保证字典序最小即可。

#include 
#include
#include
using namespace std;typedef long long ll;inline void read(int &x){ x=0;static char ch;static bool flag;flag = false; while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true; while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;}#define rg register int#define rep(i,a,b) for(rg i=(a);i<=(b);++i)#define per(i,a,b) for(rg i=(a);i>=(b);--i)const int maxn = 40010;struct Node{ int to,next;}G[maxn<<1];int head[maxn],cnt;void add(int u,int v){ G[++cnt].to = v; G[cnt].next = head[u]; head[u] = cnt;}inline void clear_G(){ memset(head,0,sizeof head); cnt = 0;}bool mark[maxn];int n,sta[maxn],top,m;inline int rev(int u){ return u^1;}#define v G[i].tobool dfs(int u){ if(mark[u]) return true; if(mark[u^1]) return false; mark[u] = true;sta[++top] = u; for(rg i = head[u];i;i=G[i].next){ if(dfs(v) == false) return false; }return true;}#undef vinline bool clear(){ top = 0;clear_G();}int p[maxn],ws[maxn];bool ans[128][9010];inline int get(int x,int m){ return (x >> 1) | ((x&1) << m-1);}int a[maxn],b[maxn],c[maxn];bool solve_next;int main(){ while(1){ clear();read(m);if(m == 0) break; n = 1 << m;int lim = ((n-1) >> 1)+1; rep(i,0,n-1) read(p[i]),ws[p[i]] = i,a[i] = i; for(rg k = m;k > 1; -- k){ memset(mark,false,sizeof mark); clear_G(); int sz = 1 << k,l = 0,r = 0; rep(i,0,n-1){ b[i] = a[i];c[i] = p[i]; if((i-l+1) == sz){ r = i; int mid = l+r >> 1; rep(j,l,r){ if((get(j-l,k)+l <= mid) != (get(ws[a[j]]-l,k)+l <= mid)){ int x = j >> 1,y = ws[a[j]] >> 1; add(x<<1,(y+lim)<<1|1);add((y+lim)<<1|1,x<<1); add(x<<1|1,(y+lim)<<1);add((y+lim)<<1,x<<1|1); }else{ int x = j >> 1,y = ws[a[j]] >> 1; add(x<<1,(y+lim)<<1);add((y+lim)<<1,x<<1); add(x<<1|1,(y+lim)<<1|1);add((y+lim)<<1|1,x<<1|1); } }l = i+1;r = 0; } } rep(i,0,n-1){ top = 0; if(dfs(i<<1) == false){ while(top) mark[sta[top--]] = false; if(dfs(i<<1|1) == false){ solve_next = true; break; } }if(solve_next) break; }if(solve_next) break; l = 0; rep(i,0,n-1){ if((i - l + 1) == sz){ rep(j,l,i){ int x = j >> 1; if(mark[x<<1|1]){ ans[m-k][x] = 1; a[get((j^1)-l,k)+l] = b[j]; }else{ ans[m-k][x] = 0; a[get(j-l,k)+l] = b[j]; } x = (j >> 1) + lim; if(mark[x<<1|1]){ ans[m+k-2][x-lim] = 1; p[get((j^1)-l,k)+l] = c[j]; }else{ ans[m+k-2][x-lim] = 0; p[get(j-l,k)+l] = c[j]; } }l = i+1; } } rep(i,0,n-1) ws[p[i]] = i; } if(solve_next){ solve_next = false; puts("-1"); continue; } rep(i,0,n-1){ if(a[i] == p[i] && a[i^1] == p[i^1]) ans[m-1][i>>1] = 0; else if(a[i] == p[i^1] && a[i^1] == p[i]) ans[m-1][i>>1] = 1; else {solve_next = true;break;} } if(solve_next){puts("-1");continue;} rep(i,0,2*m-2){ rep(j,0,(n-1)>>1){ printf("%d",ans[i][j]); }puts(""); }puts(""); } return 0;}

转载于:https://www.cnblogs.com/Skyminer/p/7132824.html

你可能感兴趣的文章
理解运算符重载 4
查看>>
快来熟练使用 Mac 编程
查看>>
第二周
查看>>
断言简介
查看>>
Node.js 入门:Express + Mongoose 基础使用
查看>>
plsql使用,为什么可以能看见其他用户的表
查看>>
一步步教你轻松学奇异值分解SVD降维算法
查看>>
Scripting Java #3:Groovy与invokedynamic
查看>>
2014-04-21-阿里巴巴暑期实习-后台研发-二面经验
查看>>
数据结构中线性表的基本操作-合并两个线性表-依照元素升序排列
查看>>
使用pager进行分页
查看>>
UVA - 1592 Database
查看>>
Min Stack
查看>>
从LazyPhp说起
查看>>
Fine Uploader文件上传组件
查看>>
javascript中的传递参数
查看>>
objective-c overview(二)
查看>>
python查询mangodb
查看>>
软件测试(基础理论一)摘
查看>>
consonant combination
查看>>