【BZOJ】3495: PA2010 Riddle 2-SAT算法
【题意】有n个城镇被分成了k个郡,有m条连接城镇的无向边。要求给每个郡选择一个城镇作为首都,满足每条边至少有一个端点是首都。n,m,k<=10^6。
【算法】2-SAT,前后缀优化建图
【题解】每个城镇只有作为首都和不是首都两种选项,即2-sat问题。
2-sat问题中所有边必须加反向边,下面过程忽略反向边。
对于一条边(x,y),如果x是0,那么y必须是1,即x-y'。(y-x'是反向边,考虑的时候忽略)
但是一个郡只有一个首都有点烦,有一种套路叫前后缀优化建图。
对于每个点x,假设一个点x+n,表示编号<=x的和x同在一个郡的点中是否有首都。
假设x和y是同一个郡的相邻编号点(y>x),那么:
1.前缀:(x+n)' - (y+n)'
2.修改:x' - (x+n)'
3.只有一个首都:(x+n)' - y
所以n*4个点和n*8条边,进行2-sat。
复杂度O(M),M=(m+3*n)*2。
#include<cctype>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int read(){
int s=,t=;char c;
while(!isdigit(c=getchar()))if(c=='-')t=-;
do{s=s*+c-'';}while(isdigit(c=getchar()));
return s*t;
}
const int maxn=;
int n,m,K,first[maxn],tot,c,B[],C[];
bool mark[maxn];
struct edge{int v,from;}e[maxn*];////
void insert(int u,int v){
tot++;e[tot].v=v;e[tot].from=first[u];first[u]=tot;
tot++;e[tot].v=u^;e[tot].from=first[v^];first[v^]=tot;
}
int dfsnum=,TOT,top,dfn[maxn],low[maxn],st[maxn],belong[maxn];
void tarjan(int x){
dfn[x]=low[x]=++dfsnum;
st[++top]=x;
for(int i=first[x];i;i=e[i].from)if(!dfn[e[i].v]){
tarjan(e[i].v);
low[x]=min(low[x],low[e[i].v]);
}else if(!belong[e[i].v])low[x]=min(low[x],dfn[e[i].v]);
if(low[x]==dfn[x]){
TOT++;
while(st[top]!=x)belong[st[top--]]=TOT;
belong[st[top--]]=TOT;
}
}
int main(){
n=read();m=read();K=read();
for(int i=;i<=m;i++){
int u=read()-,v=read()-;
insert(u<<,v<<|);
}
for(int i=;i<n;i++)insert(i<<|,(i+n)<<|);///
for(int k=;k<=K;k++){
int w=read(),p,pre=read()-;B[pre]=k;
for(int i=;i<=w;pre=p,i++){
p=read()-;B[p]=k;
insert((pre+n)<<|,(p+n)<<|);
insert((pre+n)<<|,p<<);
}
}
for(int i=;i<n*;i+=){
if(!dfn[i])tarjan(i);
if(!dfn[i^])tarjan(i^);
if(belong[i]==belong[i^]){printf("NIE");return ;}
}
printf("TAK");
return ;
}
从这道题开始,我知道了一件事:理论复杂度O(nm)的DFS版2-sat是可以无视随机被卡TLE的。
嘤嘤嘤T_T。
【BZOJ】3495: PA2010 Riddle 2-SAT算法的更多相关文章
- BZOJ.3495.[PA2010]Riddle(2-SAT 前缀优化建图)
题目链接 每个城市要么建首都要么不建,考虑2-SAT 这样一个国家内城市两两连边是很显然的,但是边数为O(n^2) 每个国家中仅有一个建首都,考虑新建前缀S[i]=1/0这2n个点表示当前国家的[1, ...
- 【刷题】BZOJ 3495 PA2010 Riddle
Description 有n个城镇被分成了k个郡,有m条连接城镇的无向边. 要求给每个郡选择一个城镇作为首都,满足每条边至少有一个端点是首都. Input 第一行有三个整数,城镇数n(1<=n& ...
- 3495: PA2010 Riddle 2-sat 前缀优化
3495: PA2010 Riddle 2-sat 前缀优化 链接 bzoj 思路 不想说啥了,看hwim的吧,我去睡觉了zZ. 代码 /******************************* ...
- 3495: PA2010 Riddle
3495: PA2010 Riddle 链接 分析: 每个点要么建首都,要么不建,并且一个点建了,会导致一些点不能建.所以可以考虑2-sat. 但是如果在每个郡里两两连边,边数是n^2的. 考虑用前缀 ...
- 【BZOJ】3495: PA2010 Riddle
题意 \(n(1 \le n \le 1000000)\)个城市,\(k(1 \le k \le n)\)个国家,\(m(1 \le m \le 1000000)\)条边.要求每个国家有且仅有一个首都 ...
- 【bzoj 3495】PA2010 Riddle
Description 有n个城镇被分成了k个郡,有m条连接城镇的无向边.要求给每个郡选择一个城镇作为首都,满足每条边至少有一个端点是首都. Input 第一行有三个整数,城镇数n(1<=n&l ...
- Bzoj 1562: [NOI2009]变换序列 匈牙利算法,二分图匹配
题目: http://cojs.tk/cogs/problem/problem.php?pid=409 409. [NOI2009]变换序列 ★★☆ 输入文件:transform.in 输出文 ...
- BZOJ 1009 HNOI2008 GT考试 KMP算法+矩阵乘法
标题效果:给定的长度m数字字符串s.求不包括子s长度n数字串的数目 n<=10^9 看这个O(n)它与 我们不认为这 令f[i][j]长度i号码的最后的字符串j位和s前者j数字匹配方案 例如,当 ...
- BZOJ 1085: [SCOI2005]骑士精神(A*算法)
第一次写A*算法(这就是A*?如果这就是A*的话,那不就只是搜索的一个优化了= =,不过h函数如果弄难一点真的有些难设计) 其实就是判断t+h(x)(t为当前步数,h(x)为达到当前状态的最小步数) ...
随机推荐
- Jquery mobile div常用属性
组件 页面 jQuery Mobile 应用了 HTML5 标准的特性,在结构化的页面中完整的页面结构分为 header. content.footer 这三个主要区域. 在 body 中插入内容块: ...
- 各种GIT代码托管工具比较
bitbucket免费支持5个开发成员的团队创建无限私有代码托管库. GOES是一个由GO语音编写的自组GIT托管服务. gitorious 是一个基于GIT版本控制系统的WEB项目托管平台,基于RU ...
- 将java开发的wordcount程序提交到spark集群上运行
今天来分享下将java开发的wordcount程序提交到spark集群上运行的步骤. 第一个步骤之前,先上传文本文件,spark.txt,然用命令hadoop fs -put spark.txt /s ...
- 搭建属于自己的NuGet服务器
文章导读 创建NuGetServer Web站点 发布站点到IIS 添加本地站点到包包数据源 在上一篇NuGet学习笔记(2) 使用图形化界面打包自己的类库 中讲解了如何打包自己的类库,接下来进行最重 ...
- Count the string HDU - 3336
题意: 求一个字符串的每个前缀在这个字符串中出现次数的加和 解析: 默默的骂一句...傻xkmp..博主心里气愤... 拓展kmp就好多了... 因为拓展kmp每匹配一次 就相当于这些前缀出现了一 ...
- [您有新的未分配科技点]数位dp:从懵X到板子(例题:HDU2089 不要62)
数位dp主要用来处理一系列需要数数的问题,一般套路为“求[l,r]区间内满足要求的数/数位的个数” 要求五花八门……比如“不出现某个数字序列”,“某种数的出现次数”等等…… 面对这种数数题,暴力的想法 ...
- IBatis Map报错10.1
检查 providers.config 把没用的给关闭掉即可
- [洛谷P4341][BJWC2010]外星联络
题目大意:给你一个长度为$n(n\leqslant3\times10^3)$的字符串,要你求出其中出现次数大于$1$的子串,并按字典序输出次数. 题解:建$SAM$后求出每个点的$size$,最后按字 ...
- [CQOI2013]新Nim游戏 线性基
题面 题面 题解 首先我们知道nim游戏先手必败当且仅当所有石堆异或和为0,因此我们的目标就是要使对手拿石堆的时候,无论如何都不能使剩下的石堆异或和为0. 对于一个局面,如果我们可以选取一些可以凑出0 ...
- 如何用Qt Python创建简单的桌面条形码应用
Qt for Python可以快速跨平台的GUI应用.这篇文章分享下如何结合Dynamsoft Barcode Reader SDK来创建一个简单的读码应用. 安装Qt for Python 官方站点 ...