博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
2-sat 问题 【例题 Flags(2-sat+线段树优化建图)】
阅读量:4553 次
发布时间:2019-06-08

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

序:

模拟赛考了一道 2-sat 问题。之前从来没听过……

考完才发现其实这个东东只要一个小小的 tarjan 求强连通分量就搞定了。

这个方法真是巧妙啊,拿来讲讲。

What is it? [・_・?]

这个算法是为了应对一些这样的条件:x1 与 x1 中至少有一个成立

算法:

既然是“2"-sat,那就要充分发挥 “two” 的优势,由于x1限制关系,有一些点我们选了后,有一些点就不能选了,那我们就只能选另一个点了满足 x2。

我们把 a 想它必须选的点 b 连有向边,这样就构成了一个图,判定的话,判断是否有两个不能同时存在的点在一个强连通分量中就好了!

这有一位大佬写的比我更好

当然重点是讲模拟赛的题!

例题  Flags:

题目大意:数轴上有 n 个旗子,第 i 个可以插在坐标 xi 或者 yi,最大化两两旗子之间的最小距离。

题解:

我们可以二分答案,转化为一个 2-sat 问题。

二分最小距离 d,那么一个点 a 向左向右 d 的 b 点都不能选,那么选了 a 就必须选 b 的另一个位置,然后我们连边,最后判断是不是有一个点的两个位置是不是在一个强连通分量里,在则不能,否则可以。

这题还有一个点就是如果直接建边的话,就有 $n^2$ 条边,你会发现这题一个点的连边都是连续的,那就不妨线段树优化建图。具体思想。

CODE:

1 #include
2 #include
3 #include
4 #include
5 #include
6 using namespace std; 7 8 int v[100005]; 9 int n,x,y,tot=0,h[100005]; 10 int scc[100005],dfn[100005],low[100005],C,cnt; 11 bool vis[100005]; 12 struct Edge{ 13 int x,next; 14 }e[5000000]; 15 pair
a[20005]; 16 stack
s; 17 18 inline void add_edge(int x,int y){ 19 e[++tot].x=y; 20 e[tot].next=h[x],h[x]=tot; 21 } 22 23 void tarjan(int x){ 24 dfn[x]=low[x]=++cnt; 25 s.push(x),vis[x]=true; 26 for(int i=h[x];~i;i=e[i].next){ 27 if(!dfn[e[i].x]){ 28 tarjan(e[i].x),low[x]=min(low[x],low[e[i].x]); 29 }else if(vis[e[i].x]){ 30 low[x]=min(low[x],dfn[e[i].x]); 31 } 32 } 33 if(dfn[x]==low[x]){ 34 C++; 35 int tmp; 36 for(;;){ 37 tmp=s.top(); 38 vis[tmp]=false,scc[tmp]=C; 39 s.pop(); 40 if(tmp==x)break; 41 } 42 } 43 } 44 45 void build(int o,int l,int r){ 46 if(r-l==1){ 47 add_edge(o+n*2,a[l].second^1); 48 return; 49 } 50 add_edge(o+n*2,(o<<1)+n*2); 51 add_edge(o+n*2,(o<<1|1)+n*2); 52 int mid=l+r>>1; 53 build(o<<1,l,mid),build(o<<1|1,mid,r); 54 } 55 56 void link(int o,int l,int r,int x,int y,int a){ 57 if(l>=x&&r<=y){ 58 add_edge(a,o+n*2); 59 return; 60 } 61 int mid=l+r>>1; 62 if(x
<<1,l,mid,x,y,a); 63 if(y>mid)link(o<<1|1,mid,r,x,y,a); 64 } 65 66 inline pair
get(int x,int len){ 67 int l=0,r=x; 68 pair
ans; 69 while(l
>1; 71 if(a[x].first-a[mid].first
>1; 78 if(a[mid].first-a[x].first
x=get(i,d); 94 if(i
>1;115 if(check(mid))l=mid;116 else r=mid-1;117 }118 printf("%d",l);119 }

转载于:https://www.cnblogs.com/ezoiLZH/p/9465026.html

你可能感兴趣的文章
vs2013 安装boost1.59
查看>>
[恢]hdu 2503
查看>>
调用动态库时声明的参数个数不一致导致的问题
查看>>
003 Python与类C语言的区别(未完)
查看>>
tomcat eclipse mysql 安装
查看>>
Linux查看CPU和内存使用情况[转]
查看>>
Delegte的BeginInvoke
查看>>
jQuery设计思想
查看>>
“嗑瓜子理论”——员工激励与管理
查看>>
状压DP 拯救莫莉斯
查看>>
入坑 可持久化线段树——主席树
查看>>
eclipse中设定文档注释
查看>>
CSS Hack及常用的技巧
查看>>
phpcms
查看>>
iOS homekit使用说明
查看>>
第 12 章 命令模式【Command Pattern】
查看>>
Uva 514-铁轨 Rails
查看>>
Java与数据库数据类型对应表
查看>>
服务治理要先于SOA
查看>>
程序员晋级CTO之路的8大准则
查看>>