UOJ 210 [UER #6]寻找罪犯
来源:互联网 发布:公司美工属于什么部门 编辑:程序博客网 时间:2024/06/03 17:40
2-SAT
首先2-SAT的tarjan做适用于一类如果A->B,则一定有B’->A’的对称的图。
一个强联通分量里的所有点,要么一起选要么一起不选,那就缩起来。
一个重要的结论是如果一个强联通分量里同时有A和A’,则此图无解,否则一定有解。
无解的情况显然正确。
有解的情况考虑构造。每次随便从点集里抓一个点A出来,选中A的所有可达点,删去所有可达A’的点。显然这是可以做到的。
那这样会不会把图弄成无解?考虑如果一个B->A,那么选了A及其可达点,那B选不选是不影响的。对于不可达A的显然也不影响,因此可以这样构造。
一个特例是存在A->A’的边,那这样选A就挂了,因此逆拓扑序 来构造才是更一般的做法。
#include<cstdio>#include<vector>#include<algorithm>#define N 600005using namespace std;namespace runzhe2000{ int read() { int r = 0; char c = get } vector<int> vec[N]; int n, nn, m, tmp, ecnt, last[N], dfn[N], low[N], timer, sta[N], stacnt, bcnt, bel[N], insta[N]; struct edge{int next, to;}e[N*10]; struct state{int a, b, type;}st[N]; void addedge(int a, int b) { e[++ecnt] = (edge){last[a], b}; last[a] = ecnt; } void tarjan(int x) { dfn[x] = low[x] = ++timer; sta[++stacnt] = x; insta[x] = 1; for(int i = last[x]; i; i = e[i].next) { int y = e[i].to; if(!dfn[y]) tarjan(y), low[x] = min(low[x], low[y]); else if(insta[y])low[x] = min(low[x], dfn[y]); } if(low[x] == dfn[x]) { bel[x] = ++bcnt; insta[x] = 0; for(; sta[stacnt] != x; stacnt--) bel[sta[stacnt]] = bcnt, insta[sta[stacnt]] = 0; stacnt--; } } void main() { scanf("%d%d",&n,&m); nn = n+n; tmp = n+n+m+m+1; for(int i = 1; i <= m; i++) { scanf("%d%d%d",&st[i].a,&st[i].b,&st[i].type); addedge(st[i].a, i+nn); addedge(i+nn+m, st[i].a+n); addedge(i+nn, st[i].b+(st[i].type?0:n)); addedge(st[i].b+(st[i].type?n:0), i+nn+m); vec[st[i].a].push_back(i); } for(int i = 1; i <= n; i++) { for(int j = 0, siz = vec[i].size(); j < siz; j++) { //tmp+j pre tmp+siz+j suf addedge(tmp+j, vec[i][j]+nn); addedge(tmp+siz+j, vec[i][j]+nn); j ? addedge(tmp+j, tmp+j-1) , addedge(vec[i][j]+nn+m, tmp+j-1) : void(); j != siz-1 ? addedge(tmp+siz+j, tmp+siz+j+1), addedge(vec[i][j]+nn+m, tmp+siz+j+1) : void(); } tmp += (vec[i].size()<<1); } for(int i = 1; i <= tmp; i++) if(!dfn[i]) tarjan(i); int cnt = 0; for(int i = 1; i <= n; i++) { if(bel[i] == bel[i+n]) return (void)puts("Impossible"); cnt += bel[i] > bel[i+n]; } for(int i = 1; i <= m; i++) if(bel[i+nn] == bel[i+nn+m]) return (void)puts("Impossible"); printf("%d\n",cnt); for(int i = 1; i <= n; i++) if(bel[i] > bel[i+n]) printf("%d ",i); }}int main(){ runzhe2000::main();}
0 0
- UOJ 210 [UER #6]寻找罪犯
- 【UOJ #210】【UER #6】寻找罪犯 (2-SAT)
- 【UOJ #210】【UER #6】寻找罪犯 (2-sat 详解)
- [杂题 计数] UOJ#209【UER #6】寻找罪犯
- #210. 【UER #6】寻找罪犯
- UOJ #210. 【UER #6】寻找罪犯 2-sat 前缀优化建边 详解
- [UOJ]210 寻找罪犯 2-Sat 前缀和优化
- UOJ210【UER #6】寻找罪犯 (2-SAT前后缀优化建边)
- 【UOJ #209】【UER #6】票数统计
- [uoj#209][UER#6A]票数统计
- 【UOJ #209】【UER #6】票数统计
- 【UOJ 209】【UER #6】票数统计
- UOJ 245 [UER #7]天路
- UOJ#245. 【UER #7】天路
- uoj 246. 【UER #7】套路
- 【UOJ 244】【UER #7】短路
- 【UOJ 246】【UER #7】套路
- UOJ #244. 【UER #7】短路
- React/React Native 的ES5 ES6写法对照
- java集合
- 升级docker并构建自己的app
- Practice_Codeforces Round #408 (Div. 2)
- eclipse工具打包可执行关联jar包的步骤
- UOJ 210 [UER #6]寻找罪犯
- eclipse搭建SSH框架(Spring+SpringMVC+Hibernate)
- 百度2017春招笔试真题
- UVA
- LeetCode : Min Stack
- BZOJ 1927 [Sdoi2010]星际竞速
- 源码-Integer的缓存
- this关键字——java
- 织梦DEDE系统建站 站长必备使用技巧 绝对的干货 掌柜呕心沥血总结