[OpenJudge 3063]罪犯问题

试题描述

一天,警官抓获了N个嫌犯,审问N个罪犯的途中,作为警长助手的你突然发现其中被确定为罪犯的K号人是你曾经出生入死的兄弟,你不能眼睁睁看着他被抓进牢里。

审问完了嫌犯之后,发现每个人都说话了,并且每个人只说了一句话,说的话形式有两种,“XXX是罪犯”以及“XXX不是罪犯”,并且罪犯说的都是假话,不是罪犯的说的都是真话(每人说的话均不是说自己)。

因为见过其中M个人的通缉令(不包括你的兄弟),镇长可以确定这M个人是罪犯。

通过这些情况可推断出大部分人是不是罪犯。每个人说话的内容都已经存入了资料库之中,现在你需要冒险修改资料库中某些人说话的内容使得你兄弟摆脱的罪犯嫌疑(必须修改后确定他不是罪犯)。

当然修改后的资料库数据不能存在矛盾,修改的条数越多,风险也就越大,现在希望你能求出最少要修改资料库中几个人说的话。

输入

第一行,三个整数N,M,K,分别表示嫌犯个数,被确定的罪犯个数以及你兄弟的编号。

第二行,M个整数,第i个整数Ti表示编号Ti的嫌犯确定是罪犯。

第3-N+2行,第i+2行有一个整数X,若X大于零,表示编号为i嫌犯的人说“X号是罪犯”;若X小于零,表示编号i为嫌犯的居民说“-X号不是罪犯”。

对于100%的数据,N<=200000,1<=M<=N;

数据保证嫌犯说的话不存在矛盾,且K号本为罪犯且未在通缉令上。

输出

仅一个整数,表示最少需修改资料库中几人说的话,使得你兄弟摆脱罪犯的嫌疑。

输入示例

  1.  
  2. -
  3. -
  4. -

输出示例

  1.  

数据规模及约定

见“输入

题解

这题挺绕的,我题意理解了半天。稍加分析发现给出的信息是正的还是负的并不影响最终答案,因为题目中保证了输入合法。

那么对于一条给出的信息“x 说 y (不)是罪犯”,其实是告诉我们,如果确定了 x 的身份,则能够确定 y 的身份;反之,如果知道了 y 的身份,就进一步能确定 x 的身份。那么现在有 m 个人的身份已知,目的是不能通过这 m 个已知的人的身份确定 k 的身份。再进一步解释就是:对于每一条信息建双向边,割断最少数量的边,使得从给定的 m 个人出发,没有一条路径能够到达 k;这显然就是一个最小割了,建一个超级源点向给定的 m 人连容量无穷的边,再把 k 看成汇点,跑一边最小割就行了。

  1. #include <iostream>
  2. #include <cstring>
  3. #include <cstdio>
  4. #include <cmath>
  5. #include <algorithm>
  6. #include <stack>
  7. #include <vector>
  8. #include <queue>
  9. #include <cstdlib>
  10. using namespace std;
  11.  
  12. int read() {
  13. int x = 0, f = 1; char c = getchar();
  14. while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }
  15. while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }
  16. return x * f;
  17. }
  18.  
  19. #define maxn 200010
  20. #define maxm 801010
  21. #define oo 2147483647
  22.  
  23. struct Edge { int from, to, flow; } ;
  24. struct Dinic {
  25. int n, m, s, t, head[maxn], next[maxm];
  26. Edge es[maxm];
  27. int vis[maxn], Q[maxn], hd, tl;
  28. int cur[maxn];
  29. void init(int _) {
  30. n = _;
  31. m = 0; memset(head, -1, sizeof(head));
  32. return ;
  33. }
  34. void AddEdge(int a, int b, int c) {
  35. es[m] = (Edge){ a, b, c }; next[m] = head[a]; head[a] = m++;
  36. return ;
  37. }
  38. bool BFS() {
  39. memset(vis, 0, sizeof(vis));
  40. hd = tl = 0; Q[++tl] = s;
  41. vis[s] = 1;
  42. while(hd < tl) {
  43. int u = Q[++hd];
  44. for(int i = head[u]; i != -1; i = next[i]) {
  45. Edge& e = es[i];
  46. if(!vis[e.to] && e.flow) {
  47. vis[e.to] = vis[u] + 1;
  48. Q[++tl] = e.to;
  49. }
  50. }
  51. }
  52. return vis[t] > 0;
  53. }
  54. int DFS(int u, int a) {
  55. if(u == t || !a) return a;
  56. int flow = 0, f;
  57. for(int& i = cur[u]; i != -1; i = next[i]) {
  58. Edge& e = es[i];
  59. if(vis[e.to] == vis[u] + 1 && (f = DFS(e.to, min(a, e.flow)))) {
  60. flow += f; a -= f;
  61. e.flow -= f; es[i^1].flow += f;
  62. if(!a) return flow;
  63. }
  64. }
  65. return flow;
  66. }
  67. int MinCut(int _, int __) {
  68. s = _; t = __;
  69. int flow = 0;
  70. while(BFS()) {
  71. for(int i = 1; i <= n; i++) cur[i] = head[i];
  72. flow += DFS(s, oo);
  73. }
  74. return flow;
  75. }
  76. } sol;
  77.  
  78. int main() {
  79. int n = read(), m = read(), k = read();
  80.  
  81. sol.init(n + 2); int s = n + 1, t = n + 2;
  82. for(int i = 1; i <= m; i++) {
  83. int x = read();
  84. sol.AddEdge(s, x, oo), sol.AddEdge(x, s, 0);
  85. }
  86. for(int i = 1; i <= n; i++) {
  87. int x = abs(read());
  88. sol.AddEdge(i, x, 1); sol.AddEdge(x, i, 1);
  89. }
  90. sol.AddEdge(k, t, oo); sol.AddEdge(t, k, 0);
  91.  
  92. printf("%d\n", sol.MinCut(s, t));
  93.  
  94. return 0;
  95. }

[OpenJudge 3063]罪犯问题的更多相关文章

  1. 关押罪犯 and 食物链(并查集)

    题目描述 S 城现有两座监狱,一共关押着N 名罪犯,编号分别为1~N.他们之间的关系自然也极不和谐.很多罪犯之间甚至积怨已久,如果客观条件具备则随时可能爆发冲突.我们用"怨气值"( ...

  2. 并查集补集作法 codevs 1069 关押罪犯

    1069 关押罪犯 2010年NOIP全国联赛提高组  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond 题解       题目描述 Description ...

  3. NOIP2010关押罪犯[并查集|二分答案+二分图染色 | 种类并查集]

    题目描述 S 城现有两座监狱,一共关押着N 名罪犯,编号分别为1~N.他们之间的关系自然也极不和谐.很多罪犯之间甚至积怨已久,如果客观条件具备则随时可能爆发冲突.我们用“怨气值”(一个正整数值)来表示 ...

  4. 【OpenJudge 8463】Stupid cat & Doge

    http://noi.openjudge.cn/ch0204/8463/ 挺恶心的一道简单分治. 一开始准备非递归. 大if判断,后来发现代码量过长,决定大打表判断后继情况,后来发现序号不对称. 最后 ...

  5. 【OpenJudge 191】【POJ 1189】钉子和小球

    http://noi.openjudge.cn/ch0405/191/ http://poj.org/problem?id=1189 一开始忘了\(2^{50}\)没超long long差点写高精度Q ...

  6. 【OpenJudge 1665】完美覆盖

    http://noi.openjudge.cn/ch0405/1665/?lang=zh_CN 状压水题,手动转移 #include<cstdio> #include<cstring ...

  7. 【OpenJudge 1793】矩形覆盖

    http://noi.openjudge.cn/ch0405/1793/ 好虐的一道题啊. 看数据范围,一眼状压,然后调了好长时间QwQ 很容易想到覆盖的点数作为状态,我用状态i表示至少覆盖状态i表示 ...

  8. OpenJudge 2990:符号三角形 解析报告

    2990:符号三角形 总时间限制:  1000ms       内存限制:  65536kB 描述 符号三角形的第1行有n个由“+”和”-“组成的符号 ,以后每行符号比上行少1个,2个同号下面是”+“ ...

  9. NOIP提高组2010 关押罪犯

    题目描述 S 城现有两座监狱,一共关押着N 名罪犯,编号分别为1~N.他们之间的关系自然也极不和谐.很多罪犯之间甚至积怨已久,如果客观条件具备则随时可能爆发冲突.我们用“怨气值”(一个正整数值)来表示 ...

随机推荐

  1. linux查看cpu、内存、版本信息

    1.  查看物理CPU的个数#cat /proc/cpuinfo |grep "physical id"|sort |uniq|wc –l 2.   查看逻辑CPU的个数#cat ...

  2. mysqld参数配置

    这个文件超级大, 查了一下, 大概的作用如下 是储存的格式INNODB类型数据状态下,ibdata用来储存文件的数据而库名的文件夹里面的那些表文件只是结构而已 由于mysql4.1默认试innodb, ...

  3. struts2升级报ActionContextCleanUp<<is deprecated。Please use the new filters

    把web.xml中配置struts.xml的文件改成 <?xml version="1.0" encoding="UTF-8"?> <web- ...

  4. Java基础-String、StringBuffer、StringBuilder

    看下面这段代码: public class Main { public static void main(String[] args) { String string = ""; ...

  5. Java基础-数据类型int,short,char,long,float,double,boolean,byte

    Java语言是静态类型的(statical typed),也就是说所有变量和表达式的类型再编译时就已经完全确定.由于是statical typed,导致Java语言也是强类型(Strong typed ...

  6. jdownload的使用

    <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <m ...

  7. 【POJ 1260】Pearls

    题 题意 有n个(n≤100)等级的珍珠,等级越高单价越高,要购买一种等级的珍珠就要多付10*单价,现在需要购买一些等级的珍珠一定数量,若买更高等级的珍珠更便宜则可以买更高等级的珍珠,求最少花费. 分 ...

  8. 【bzoj1853】 Scoi2010—幸运数字

    http://www.lydsy.com/JudgeOnline/problem.php?id=1853 (题目链接) 今天考试考了容斥,结果空知道结论却不会写→_→ 题意 求区间中不含6,8两个数字 ...

  9. BZOJ4241 历史研究

    Description IOI国历史研究的第一人——JOI教授,最近获得了一份被认为是古代IOI国的住民写下的日记.JOI教授为了通过这份日记来研究古代IOI国的生活,开始着手调查日记中记载的事件. ...

  10. BZOJ2818 欧拉函数

    题意:求1--n中满足gcd(x,y)的值为质数的数对(x,y)的数目 ( (x,y)和(y,x)算两个 ) sol: 设p[i]是一个质数,那么以下两个命题是等价的: 1.gcd(x,y)=1 2. ...