bzoj2215: [Poi2011]Conspiracy 2-sat

链接

https://www.lydsy.com/JudgeOnline/problem.php?id=2215

思路

一个点的属性为去当同谋者和后勤两种

求出一种方案来很简单(只需要用简单的2-sat)

我们发现一条特别重要的性质:

一个方案只会由已经求出的其他任意一种方案改变一方的一个人得来

(基本看出来就稳了)

因为两个人不能同时过去(显然)

那么我们先求出一种方案

然后统计ok[i],表示i到对面冲突的点的个数

显然只有几种情况(大力分情况讨论)

①.一个间谍去后勤

②.一个后勤区去间谍

就是ok==0的个数(注意双方都不能为0个人)

③.间谍和后勤互换(容易发现交换的两个人一定一个是0,一个是1)

好了。

错误

tarjan求方案的方向居然写反了、、、

还有mp的i+n没减n

代码

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <vector>
  4. #define iter vector<int>::iterator
  5. const int N=5007;
  6. using namespace std;
  7. int read() {
  8. int x=0,f=1;char s=getchar();
  9. for(;s>'9'||s<'0';s=getchar()) if(s=='-') f=-1;
  10. for(;s>='0'&&s<='9';s=getchar()) x=x*10+s-'0';
  11. return x*f;
  12. }
  13. int n,ok[N<<1],dsr;
  14. bool mp[N][N];
  15. vector<int> ans[2];
  16. struct node {
  17. int v,nxt;
  18. }e[N*N];
  19. int head[N<<1],tot;
  20. void add(int u,int v) {
  21. e[++tot].v=v;
  22. e[tot].nxt=head[u];
  23. head[u]=tot;
  24. }
  25. int dfn[N<<1],low[N<<1],stak[N<<1],top,cnt,belong[N<<1],vis[N<<1];
  26. void tarjan(int u) {
  27. dfn[u]=low[u]=++cnt;
  28. vis[u]=1;
  29. stak[++top]=u;
  30. for(int i=head[u];i;i=e[i].nxt) {
  31. int v=e[i].v;
  32. if(!dfn[v]) {
  33. tarjan(v);
  34. low[u]=min(low[u],low[v]);
  35. } else if(vis[v]) {
  36. low[u]=min(low[u],dfn[v]);
  37. }
  38. }
  39. if(low[u]==dfn[u]) {
  40. belong[0]++;
  41. while(stak[top]!=u) {
  42. vis[stak[top]]=0;
  43. belong[stak[top]]=belong[0];
  44. top--;
  45. } top--;
  46. vis[u]=0;
  47. belong[u]=belong[0];
  48. }
  49. }
  50. int main() {
  51. n=read();
  52. for(int i=1;i<=n;++i) {
  53. int k=read();
  54. for(int j=1;j<=k;++j) mp[i][read()]=1;
  55. }
  56. for(int i=1;i<=n;++i) {
  57. for(int j=1;j<i;++j) {
  58. if(mp[i][j]) {
  59. add(i,j+n),add(j,i+n);
  60. } else {
  61. add(i+n,j),add(j+n,i);
  62. }
  63. }
  64. }
  65. for(int i=1;i<=n+n;++i)
  66. if(!dfn[i])
  67. tarjan(i);
  68. for(int i=1;i<=n;++i) {
  69. if(belong[i]==belong[i+n]) {
  70. puts("0");
  71. return 0;
  72. }
  73. }
  74. for(int i=1;i<=n;++i) {
  75. if(belong[i] < belong[i+n]) ans[0].push_back(i);
  76. else ans[1].push_back(i+n);
  77. }
  78. if(ans[0].size()&&ans[1].size()) dsr++;
  79. for(iter i=ans[0].begin();i!=ans[0].end();++i) {
  80. for(iter j=ans[1].begin();j!=ans[1].end();++j) {
  81. if(!mp[*i][*j-n]) ok[*i]++;
  82. }
  83. }
  84. for(iter i=ans[1].begin();i!=ans[1].end();++i) {
  85. for(iter j=ans[0].begin();j!=ans[0].end();++j) {
  86. if(mp[*i-n][*j]) ok[*i]++;
  87. }
  88. }
  89. int siz_0[2]={};
  90. for(int k=0;k<=1;++k)
  91. for(iter i=ans[k].begin();i!=ans[k].end();++i)
  92. if(!ok[*i]) siz_0[k]++;
  93. if(ans[0].size()>1) dsr+=siz_0[0];
  94. if(ans[1].size()>1) dsr+=siz_0[1];
  95. for(iter i=ans[0].begin();i!=ans[0].end();++i) {
  96. if(ok[*i]==1) {
  97. for(iter j=ans[1].begin();j!=ans[1].end();++j) {
  98. if(!mp[*i][*j-n]&&!ok[*j]) dsr++;
  99. }
  100. }
  101. }
  102. for(iter i=ans[1].begin();i!=ans[1].end();++i) {
  103. if(ok[*i]==1) {
  104. for(iter j=ans[0].begin();j!=ans[0].end();++j) {
  105. if(mp[*i-n][*j]&&!ok[*j]) dsr++;
  106. }
  107. }
  108. }
  109. printf("%d\n",dsr);
  110. return 0;
  111. }

# bzoj2215: [Poi2011]Conspiracy 2-sat的更多相关文章

  1. bzoj2215: [Poi2011]Conspiracy

    Description Byteotia的领土被占领了,国王Byteasar正在打算组织秘密抵抗运动.国王需要选一些人来进行这场运动,而这些人被分为两部分:一部分成为同谋者活动在被占领区域,另一部分是 ...

  2. BZOJ2215[Poi2011]Conspiracy——2-SAT+tarjan缩点

    题目描述 Byteotia的领土被占领了,国王Byteasar正在打算组织秘密抵抗运动.国王需要选一些人来进行这场运动,而这些人被分为两部分:一部分成为同谋者活动在被占领区域,另一部分是后勤组织在未被 ...

  3. POI2011题解

    POI2011题解 2214先咕一会... [BZOJ2212][POI2011]Tree Rotations 线段树合并模板题. #include<cstdio> #include< ...

  4. bzoj AC倒序

    Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...

  5. POI做题笔记

    POI2011 Conspiracy (2-SAT) Description \(n\leq 5000\) Solution 发现可拆点然后使用2-SAT做,由于特殊的关系,可以证明每次只能交换两个集 ...

  6. 「POI2011 R1」Conspiracy

    「POI2011 R1」Conspiracy 解题思路 : 问题转化为,将点集分成两部分,其中一部分恰好组成一个团,其中另一部分恰好组成一个独立集. 观察发现,如果求出了一个解,那么答案最多可以在这个 ...

  7. BZOJ2527: [Poi2011]Meteors

    补一发题解.. 整体二分这个东西,一开始感觉复杂度不是很靠谱的样子 问了po姐姐,说套主定理硬干.. #include<bits/stdc++.h> #define ll long lon ...

  8. 多边形碰撞 -- SAT方法

    检测凸多边形碰撞的一种简单的方法是SAT(Separating Axis Theorem),即分离轴定理. 原理:将多边形投影到一条向量上,看这两个多边形的投影是否重叠.如果不重叠,则认为这两个多边形 ...

  9. BZOJ2276: [Poi2011]Temperature

    2276: [Poi2011]Temperature Time Limit: 20 Sec  Memory Limit: 32 MBSubmit: 293  Solved: 117[Submit][S ...

随机推荐

  1. [13]Windows 内核情景分析 --- 网络通信

    典型的基于tcpip协议套接字方式的网络通信模块层次: 应用程序 socket api WS2_32.dll socket irp Afd.sys tdi irp Tcpip.sys 回调函数接口 各 ...

  2. 一 js数据类型

    一.简单的数据对象 ------1.小数 var fNum = 1.02; ------2.整数 var iNum = 1; ------3.逻辑变量 var bNum = true; 二.复杂的数据 ...

  3. 使用js调用js

    直接上源码: <div class="choose"> choose a mode<br> <hr> <button type=" ...

  4. Sitecore系统教程之模板理解

    Sitecore中的所有内容都是一个项目.模板也是如此.Sitecore中的模板是一个项目,它定义了其他项目的结构和行为.Sitecore中的每个项目都是某个模板的实例.模板还可以定义它分解成的部分和 ...

  5. 4.7 引入NULL对象

    [1]引入NULL对象范例 Book.h #ifndef _BOOK_H #define _BOOK_H #include <string> using namespace std; cl ...

  6. 刨根究底字符编码之—UTF-16编码方式

    在网上已经转悠好几天了, 这篇文章让我知道了UTF-16的前世今生, 感谢作者https://cloud.tencent.com/developer/article/1384687 1. UTF-16 ...

  7. python 列表推导

    废话不多说,直接上代码 #coding=utf-8 def getitem(index, element): return '%d: %s' % (index, element) def getite ...

  8. RocketMQ 顺序消费只消费一次 坑

    rocketMq实现顺序消费的原理 produce在发送消息的时候,把消息发到同一个队列(queue)中,消费者注册消息监听器为MessageListenerOrderly,这样就可以保证消费端只有一 ...

  9. 苹果企业版签名分发相关问题,蒲公英签名,fir.im分发,安装ipa设置信任

    苹果企业版签名分发相关问题,蒲公英签名,fir.im分发,安装ipa设置信任蒲公英 - 高效安全的内测应用发布.管理平台https://www.pgyer.com/app/signature分发版 2 ...

  10. 常用的node.js模块

    一.url模块1.url.parse:将一个url转换成一个对象 1)参数1:url 2)参数2:布尔值 3)如果参数2是一个true的情况下会将query解析成一个对象2.url.format:将一 ...