tarjan的运用

this is a problem:link

2-SAT处理的是什么

首先,把「2」和「SAT」拆开。SAT 是 Satisfiability 的缩写,意为可满足性。即一串布尔变量,每个变量只能为真或假。要求对这些变量进行赋值,满足布尔方程。

所以看这道题

若ai为真或aj为真,所以当ai为真时aj必须为假,若aj为真时ai必须为假

所以假设i为ai为真,i+n为ai为假

所以建边(i,j+n),(j,i+n),连接u,v表示选u就要选v

然后用可能出现环,所以用tarjan缩点表示若i,j在同一强联通分量中,那么他们两个必须要选

然后可以想无解情况,若i于i+n都在同一强连通分量中,于是无解,因为他们两个都必须要选,但却不能都选

然后想怎么输出解

因为拓扑序的关系 拓扑序在前的点有可能能够到达拓扑序靠后的点 而靠后的一定无法到达靠前的 因此选择靠后的一定能够保证出合法解 而选择靠前的可能会导致前面的点存在一条通路到达后面的点致使答案出现错误 这样可以感性理解,至于证明利用了建图过程中的对称性。什么意思呢1,就是tarjan为反拓扑顺序,所以说就要选择强连通编号中最大的

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<algorithm>
  5. using namespace std;
  6. inline int read()
  7. {
  8. int f=,ans=;char c;
  9. while(c<''||c>''){if(c=='-')f=-;c=getchar();}
  10. while(c>=''&&c<=''){ans=ans*+c-'';c=getchar();}
  11. return f*ans;
  12. }
  13. struct node{
  14. int u,v,nex;
  15. }x[];
  16. int n,m,head[],cnt,dfn[],st[],num,top,col,co[],low[],tot;
  17. void tarjan(int xx)
  18. {
  19. low[xx]=dfn[xx]=++num;
  20. st[++tot]=xx;
  21. for(int i=head[xx];i!=-;i=x[i].nex)
  22. {
  23. int v=x[i].v;
  24. if(!dfn[v])
  25. {
  26. tarjan(v);
  27. low[xx]=min(low[xx],low[v]);
  28. }
  29. else if(!co[v]) low[xx]=min(low[xx],dfn[v]);
  30. }
  31. if(dfn[xx]==low[xx])
  32. {
  33. co[xx]=++col;
  34. while(st[tot]!=xx)
  35. {
  36. co[st[tot]]=col;
  37. tot--;
  38. }
  39. tot--;
  40. }
  41. return;
  42. }
  43. void add(int u,int v)
  44. {
  45. x[cnt].u=u,x[cnt].v=v,x[cnt].nex=head[u],head[u]=cnt++;
  46. }
  47. int main()
  48. {
  49. memset(head,-,sizeof(head));
  50. n=read(),m=read();
  51. for(int i=;i<=m;i++)
  52. {
  53. int a=read(),xa=read(),b=read(),yb=read();
  54. if(xa==&&yb==) add(a,b+n),add(b,a+n);
  55. if(xa==&&yb==) add(a,b),add(b+n,a+n);
  56. if(xa==&&yb==) add(a+n,b),add(b+n,a);
  57. if(xa==&&yb==) add(a+n,b+n),add(b,a);
  58. }
  59. for(int i=;i<=*n;i++)
  60. if(!dfn[i]) tarjan(i);
  61. for(int i=;i<=n;i++)
  62. if(co[i]==co[i+n]){cout<<"IMPOSSIBLE";return ;}
  63. cout<<"POSSIBLE"<<endl;
  64. for(int i=;i<=n;i++)
  65. {
  66. if(co[i]>co[i+n]) cout<<<<" ";
  67. else cout<<<<" ";
  68. }
  69. return ;
  70. }
  71. /*
  72. 3 2
  73. 1 1 3 0
  74. 3 1 1 0
  75. */

一道2-SAT的例题

和平委员会

link
试题描述
根据宪法,Byteland 民主共和国的公众和平委员会应该在国会中通过立法程序来创立。 不幸的是,由于某些党派代表之间的不和睦而使得这件事存在障碍。
此委员会必须满足下列条件:
每个党派都在委员会中恰有 1 个代表,
如果 2 个代表彼此厌恶,则他们不能都属于委员会。
每个党在议会中有 2 个代表。代表从 1 编号到 2n。 编号为 2i−1 和 2i 的代表属于第 i 个党派。
任务:写一程序读入党派的数量和关系不友好的代表对,计算决定建立和平委员会是否可能,若行,则列出委员会的成员表。
输入
第一行有两个非负整数 n 和 m。他们各自表示:党派的数量 n 和不友好的代表对 m。 接下来 m 行,每行为一对整数 a,b,表示代表 a,b 互相厌恶。
输出
如果不能创立委员会,则输出信息NIE。若能够成立,则输出包括 n 个从区间 1 到 2n 选出的整数,按升序写出,每行一个,这些数字为委员会中代表的编号。
如果委员会能以多种方法形成,程序可以只输出它们的某一个。
输入示例
3 2
1 3
2 4
输出示例
1
4
5
其他说明
数据范围与提示
1≤n≤8000,0≤m≤20000,1≤a<b≤2n

一个2-SAT的板子,就是与上一道题的区别是,上一道题必须二选一,这一次可以两个都不选,所以选择拓扑序小的(想一想,为什么)、

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<algorithm>
  5. using namespace std;
  6. inline int read()
  7. {
  8. int f=,ans=;char c;
  9. while(c<''||c>''){if(c=='-')f=-;c=getchar();}
  10. while(c>=''&&c<=''){ans=ans*+c-'';c=getchar();}
  11. return f*ans;
  12. }
  13. struct node{
  14. int u,v,nex;
  15. }x[];
  16. int n,m,cnt,head[],dfn[],low[],tot,num,st[],co[],col;
  17. void add(int u,int v)
  18. {
  19. x[cnt].u=u,x[cnt].v=v,x[cnt].nex=head[u],head[u]=cnt++;
  20. }
  21. int cx(int s)
  22. {
  23. if(s%==) return s-;
  24. else return s+;
  25. }
  26. void tarjan(int xx)
  27. {
  28. low[xx]=dfn[xx]=++num;
  29. st[++tot]=xx;
  30. for(int i=head[xx];i!=-;i=x[i].nex)
  31. {
  32. int v=x[i].v;
  33. if(!dfn[v])
  34. {
  35. tarjan(v);
  36. low[xx]=min(low[xx],low[v]);
  37. }
  38. else if(!co[v]) low[xx]=min(low[xx],dfn[v]);
  39. }
  40. if(dfn[xx]==low[xx])
  41. {
  42. co[xx]=++col;
  43. while(st[tot]!=xx)
  44. {
  45. co[st[tot]]=col;
  46. tot--;
  47. }
  48. tot--;
  49. }
  50. return;
  51. }
  52. int main()
  53. {
  54. memset(head,-,sizeof(head));
  55. n=read(),m=read();
  56. for(int i=;i<=m;i++)
  57. {
  58. int u=read(),v=read();
  59. add(u,cx(v)),add(v,cx(u));
  60. }
  61. for(int i=;i<=*n;i++)
  62. if(!dfn[i]) tarjan(i);
  63. for(int i=;i<=*n;i=i+)
  64. {
  65. if(co[i]==co[i+])
  66. {
  67. cout<<"NIE";
  68. return ;
  69. }
  70. }
  71. for(int i=;i<=*n;i=i+)
  72. {
  73. if(co[i]>co[i+]) cout<<i+<<endl;
  74. else cout<<i<<endl;
  75. }
  76. return ;
  77. }

[模板]2-SAT 问题&和平委员会的更多相关文章

  1. HDU 1814 Peaceful Commission / HIT 1917 Peaceful Commission /CJOJ 1288 和平委员会(2-sat模板题)

    HDU 1814 Peaceful Commission / HIT 1917 Peaceful Commission /CJOJ 1288 和平委员会(2-sat模板题) Description T ...

  2. 【POI2001】【HDU1814】和平委员会

    题面 Description 根据宪法,Byteland民主共和国的公众和平委员会应该在国会中通过立法程序来创立. 不幸的是,由于某些党派代表之间的不和睦而使得这件事存在障碍. 此委员会必须满足下列条 ...

  3. COGS:313. [POI2001] 和平委员会

    313. [POI2001] 和平委员会 ★★☆   输入文件:spo.in   输出文件:spo.out   评测插件时间限制:1 s   内存限制:128 MB 题目描述 根据宪法,Bytelan ...

  4. HDU1814和平委员会

    题目大意: 有n对的人,编号从1-2*n,m对的人之间互相不喜欢,每对人中必徐选1个人加入和平委员会,求字典序最小的解 -------------------------------- 2-SAT问题 ...

  5. [POI2001]和平委员会

    题目描述 根据宪法,Byteland民主共和国的公众和平委员会应该在国会中通过立法程序来创立. 不幸的是,由于某些党派代表之间的不和睦而使得这件事存在障碍. 此委员会必须满足下列条件: 每个党派都在委 ...

  6. LOJ10097和平委员会

    POI 2001 根据宪法,Byteland民主共和国的公众和平委员会应该在国会中通过立法程序来创立. 不幸的是,由于某些党派代表之间的不和睦而使得这件事存在障碍. 此委员会必须满足下列条件: 每个党 ...

  7. cogs 313. [POI2001] 和平委员会(2-SAT

    http://cogs.pro:8080/cogs/problem/problem.php?pid=pyzQimjkj 题意:有n个集合,每个集合有俩元素,要从n个中各选一个放一堆,但是有的俩不能同时 ...

  8. P5782-[POI2001]和平委员会【2-SAT】

    正题 题目链接:https://www.luogu.com.cn/problem/P5782 题目大意 \(n\)对人,每对之间恰好有一个人出席.\(m\)对仇恨关系表示两个人不能同时出席. 求是否有 ...

  9. HIT 1917 2—SAT

    题目大意:一国有n个党派,每个党派在议会中都有2个代表, 现要组建和平委员会,要从每个党派在议会的代表中选出1人,一共n人组成和平委员会. 已知有一些代表之间存在仇恨,也就是说他们不能同时被选为和平委 ...

随机推荐

  1. selenium 结合 docker 构建分布式测试环境 (初学者视角)

    前言:随着自动化测试越学越深,深深觉得有太多的东西需要总结. 1.记录下学习中遇到的坑,当做学习笔记.2.有前人路过看到文章中比较落后的做法,请务必一定要指教.(因为是初学者视角,很多东西只是走通而已 ...

  2. request,logging,ConfigParser——接口框架

    做一个将参数和用例分开放置,并且输出log的接口测试框架 我的框架如下所示 Log文件用来设置log输出文件,需要时可以在用例内调用输出,config用来填写一切需要的参数信息,jiekou_post ...

  3. 408. Add Binary【LintCode java】

    Description Given two binary strings, return their sum (also a binary string). Example a = 11 b = 1 ...

  4. elasticsearch备份与恢复

    备注:以下代码在kibana插件下运行: # 创建一个备份用的仓库# type:fs文件系统# 支持Shared filesystem, Amazon S3, HDFS和Azure #Cloud# l ...

  5. 袋鼠云研发手记 | 袋鼠云EasyManager的TypeScript重构纪要

    作为一家创新驱动的科技公司,袋鼠云每年研发投入达数千万,公司80%员工都是技术人员,袋鼠云产品家族包括企业级一站式数据中台PaaS数栈.交互式数据可视化大屏开发平台Easy[V]等产品也在迅速迭代.在 ...

  6. eclipse版本信息及操作系统

    一.查看版本信息: 进入到eclipse安装目录下,有一个.eclipseproduct文件,用记事本打开,就可以知道版本了,后面version=的值就是版本 二.是否为32位操作系统: 找到ecli ...

  7. wepy中如何使用stylus等样式预处理器

    wepy中如何使用stylus等样式预处理器 一.如何在wepy中使用stylus 1.安装wepy-compiler-stylus(以及stylus, stylus-loader) npm inst ...

  8. mysql常用语句入门整理

    这篇属于小白入门级别,如果你已经高手可以直接跳过 1.运行数据库mysqld.exe,客户端直接mysql -uroot(root是默认用户名) -p 2 showdatabases,showtabl ...

  9. Beta周王者荣耀交流协会第六次会议

    1.立会照片 成员王超,高远博,冉华,王磊,王玉玲,任思佳,袁玥全部到齐. master:袁玥 2. 时间跨度 2017年11月15日 19:00 — 19:10 ,总计10分钟. 3. 地点 一食堂 ...

  10. 又要开始新的征程了hhh(这次内容比较感兴趣)

    因为做英雄部分,既是我比较感兴趣,又很符合这次c++学习的目的,所以我很开心. 其实从小玩的RPG,即时战略和回合制游戏不算少,对于属性方法其实都算不上陌生.但是还是在网上找了一些学习资源. http ...