图论建模-杀人游戏

杀人游戏

[中山市选]杀人游戏
题目描述一位冷血的杀手潜入Na-wiat,并假装成平民。警察希望能在 N N N个人里面,查出谁是杀手。警察能够对每一个人进行查证,假如查证的对象是平民,他会告诉警察,他认识的人,谁是杀手,谁是平民。假如查证的对象是杀手,杀手将会把警察干掉。现在警察掌握了每一个人认识谁。每一个人都有可能是杀手,可看作他们是杀手的概率是相同的。
问:根据最优的情况,保证警察自身安全并知道谁是杀手的概率最大是多少?
输入格式
第一行有两个整数 N , M N,M N,M。
接下来有 M M M 行,每行两个整数 x , y x,y x,y,表示 x x x 认识 y y y( y y y 不一定认识 x x x ,例如President同志) 。
注:原文zz敏感内容已替换
输出格式
仅包含一行一个实数,保留小数点后面 6 6 6 位,表示最大概率。
样例 #1

样例输入 #1

5 4
1 2
1 3
1 4
1 5

样例输出 #1

0.800000

提示

警察只需要查证 1 1 1。假如 1 1 1是杀手,警察就会被杀。假如 1 1 1不是杀手,他会告诉警察 2 , 3 , 4 , 5 2,3,4,5 2,3,4,5谁是杀手。而 1 1 1是杀手的概率是 0.2 0.2 0.2,所以能知道谁是杀手但没被杀的概率是 0.8 0.8 0.8。

对于 100 % 100\% 100%的数据有 1 ≤ N ≤ 100000 , 0 ≤ M ≤ 300000 1≤N≤100000,0≤M≤300000 1≤N≤100000,0≤M≤300000。
题意简述:给定一张有向图上有 n n n个点,每个点都有同等的概率为黑点,黑点只有一个,从一个节点出发可以知道所有可达点度数,求确定黑点的概率。

如何想到图论建模呢,事实上,当我们面对类似于这种单向的二元关系问题,并且需要借助关系确定某些信息时,便可以想图论建模的思路

那么梳理一下思路,如果我们将每个人认识的人进行连一条有向边,记作 ( u , v ) (u,v) (u,v),那么我们再来考虑这张图

很明显,如果若干个点处于同一个 S C C SCC SCC之中,问哪一个元素都是一样的,这启发我们将图缩点,变成一个 D A G DAG DAG,因为是在最优情况下,于是我们可以思考如何用最少的次数确定每一个元素

引理

一般情况下,确定每一个元素的颜色,最少的操作次数一定为零入度点的个数,
先证必要性:

显然,零入度点不可能被其他点所确定,故至少需要零入度点个数的操作次数才能覆盖整张图

再证充分性:

一个点 v v v被覆盖当且仅当至少存在一条边 ( u , v ) (u,v) (u,v)且 u u u被覆盖,那么我们对于每一个点类似递归思想一直追溯到不存在这样的边,此时这个最后追溯到的点确定之后 v v v也就确定了,故数学归纳法易证

然后我们来思考有无特殊情况,考虑原图中的一个点 p p p在怎样的情况下才可以不选择而被确定。若 p p p点是一个孤立点,亦或者它所连的点的度数均大于等于2,此时这个点就可以先不急着需要它的颜色,那么我们可以将其放在最后解决,那么在所有满足要求的点 p p p中,有一个点会因为其他所有点都被确定了而无需确定,这样就可以少选一次
Q E D . QED. QED.

结合引理,我们得到了本题的算法流程

  1. 建图,执行缩点
  2. 对于缩点后的 D A G DAG DAG,统计零入度点数量,记为 c c c,统计是零入度点,所在强连通分量大小为1并且满足其所连接的强连通分量的入度均大于1的 S C C SCC SCC数量,记为 p p p
  3. 最终答案为: a n s = n − c + m i n ( p , 1 ) n ans=\frac{n-c+min(p,1)}{n} ans=nn−c+min(p,1)​

对于本题需要注意的点是,在缩点建立新图的时候,很有可能出现重边的情况,大部分使用 m a p map map进行优化,速度较慢,这里有一个更快的方式:

注意我们的 T a r j a n Tarjan Tarjan已经可以求出每一个 S C C SCC SCC包含哪些点了,我们可以设一个大小为 n n n的一维数组 v i s vis vis,对于编号为 i ∈ [ 1 , c n t ] i\in[1,cnt] i∈[1,cnt]的强连通分量进行考虑

  1. 清空 v i s vis vis,这一步可以开一个 v e c t o r vector vector记录上一个强连通分量所连接的强连通分量进行撤销,保证复杂度
  2. 遍历第 i i i个强连通分量的元素 u u u,对 u u u执行操作3
  3. 遍历 u u u的所有出边,在同一个强连通分量的不管,不在同一个强连通分量的,设后继点为 v v v,则若 v i s [ c [ v ] ] vis[c[v]] vis[c[v]]未曾标记,将其入度加一并标记,若被标记,则不管

时间复杂度 O ( M ) O(M) O(M)

本题总时间复杂度: O ( M + N ) = O ( M ) O(M+N)=O(M) O(M+N)=O(M)

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<stack>
using namespace std;
#define N 150000
#define M 650000
int head[N],n,m,ans,p,num,ver[M],nxt[M],c[N],siz[N],in[N],cnt[N],tot,scc_cnt,vis[N],dfn[N],low[N],s[N],inn[N];
int shead[N],sver[M],snxt[M],stot;
void add_s(int u,int v){snxt[++stot]=shead[u],sver[shead[u]=stot]=v;
}
vector<int>scc[N];
stack<int>t;
void add(int u,int v){nxt[++tot]=head[u],ver[head[u]=tot]=v;
}
void tarjan(int u){t.push(u);vis[u]=1;dfn[u]=low[u]=++num;for(int i=head[u];i;i=nxt[i]){int v=ver[i];if(!dfn[v]){tarjan(v);low[u]=min(low[u],low[v]);}else if(vis[v])low[u]=min(low[u],dfn[v]);}if(dfn[u]==low[u]){int v;scc_cnt++;do{v=t.top();t.pop();vis[v]=0;scc[scc_cnt].push_back(v);c[v]=scc_cnt;siz[scc_cnt]++;}while(u!=v);}
}
bool check(int a){for(int i=0;i<scc[a].size();i++){int u=scc[a][i];for(int i=head[u];i;i=nxt[i]){int v=ver[i];if(c[u]==c[v])continue;if(in[c[v]]<2)return true;}}return false;
}
void solve(){if(n==1){printf("1.000000\n");return ;};for(int i=1;i<=scc_cnt;i++){int num=0;cnt[i]=1;for(int j=0;j<siz[i];j++){int u=scc[i][j];for(int k=head[u];k;k=nxt[k]){if(cnt[c[ver[k]]])continue;in[c[ver[k]]]++;cnt[c[ver[k]]]=1;s[++num]=c[ver[k]];}} cnt[i]=0;while(num)cnt[s[num--]]=0;}int ans1=0,flag=1;for(int i=1;i<=scc_cnt;i++){if(in[i]==0){ans1++;}}if(ans1==1){printf("%.6f\n",1.0-1.0/n);return ;}for(int i=1;i<=scc_cnt;i++)if(in[i]==0&&!check(i)){ans1--;break;}printf("%.6f\n",1.0*(n-ans1)/n);return ;
}
void init(){scanf("%d%d",&n,&m);for(int i=1;i<=m;i++){int u,v;scanf("%d%d",&u,&v);add(u,v);inn[v]++;}for(int i=1;i<=n;i++)if(!dfn[i])tarjan(i);solve();
}
int main(){init();
}

杀人游戏-Tarjan相关推荐

  1. [BZOJ 2438] [中山市选2011]杀人游戏 Tarjan缩点

    这个题很容易想到正解就是缩点找入度为零的点,那么我们考虑一种特殊情况就是,一个入度为零的点我们不访问他就知道他是不是凶手,那么这样的话就是:I. 他是一个真·孤立的点 II. 他在图里但是在他的强联通 ...

  2. [中山市选]杀人游戏 (Tarjan缩点)

    题目链接 Solution 可以考虑到如果知道环内一点的身份,如果凶手在其中就查出来了,同时不会有危险. 那么对警察造成威胁的就是那些身份不明且不能从其他点转移过来的点. 那么大部答案就是缩完点之后入 ...

  3. [补档][中山市选2011]杀人游戏

    [中山市选2011]杀人游戏 题目 一位冷血的杀手潜入 Na-wiat,并假装成平民.警察希望能在 N 个人里面,查出谁是杀手. 警察能够对每一个人进行查证,假如查证的对象是平民,他会告诉警察,他认识 ...

  4. 约瑟夫环(杀人游戏)

    问题描述: 刚学数据结构的时候,我们可能用链表的方法去模拟这个过程,N个人看作是N个链表节点,节点1指向节点2,节点2指向节点3,--,节点N - 1指向节点N,节点N指向节点1,这样就形成了一个环. ...

  5. 天黑请闭眼 杀人游戏 规则

    "天黑请闭眼" "杀人游戏" 规则 杀人游戏规则 游戏概述: 这是一个锻炼表达能力.判断力.观察力.思维能力和表演能力-的游戏.每一个曾经参与游戏的人都会被它深 ...

  6. 天黑请闭眼 杀人游戏 规则 02

    "天黑请闭眼" "杀人游戏" 规则 游戏概述: 这是一个锻炼表达能力.判断力.观察力.思维能力和表演能力-的游戏.每一个曾经参与游戏的人都会被它深深的吸引住.游 ...

  7. 1504: 变态杀人狂 时间限制: 1 Sec 内存限制: 128 MB 提交: 21 解决: 10 [提交][状态][论坛] 题目描述 变态杀人狂三师弟想到一个杀人游戏 游戏规则如下: 三师

                1504: 变态杀人狂 时间限制: 1 Sec  内存限制: 128 MB 提交: 21  解决: 10 [提交][状态][论坛] 题目描述 变态杀人狂三师弟想到一个杀人游戏 ...

  8. 杀人游戏语言中英对照

    法官用语:Judge's Words 每人一张牌,请看好自己手中的牌. Each one takes one card. Please look at your own card carefully. ...

  9. 3月广州IT媒体杀人游戏比赛,就在本周五晚

    偶和几个广州IT媒体的朋友打算本周五晚 7:30,在广州的专业杀人CLUB玩杀人游戏咯,详细的请看这个联接 3月广州媒体朋友Killer Club大赛聚会报名渠道及宣传页面! http://www.w ...

最新文章

  1. Java方法详细介绍
  2. 你想要的宏基因组-微生物组知识全在这
  3. COM 组件设计与应用(十一)—— IDispatch 及双接口的调用
  4. php表单复选传值,jQuery+SpringMVC中的复选框选择与传值实例_jquery
  5. gradient渐变IE兼容处理
  6. java中Runnable和Callable的区别
  7. linux+4.4+android,Ubuntu 14.04 x64配置Android 4.4 kitkat编译环境的方法
  8. sas sql中有类似mysql的 g_SAS中的SQL
  9. 程序员除了上班,还可以怎么赚钱?
  10. Java快速入门学习笔记3 | Java语言中的表达式与操作符
  11. 20135234mqy-——信息安全系统设计基础第七周学习总结
  12. SSH和SSM有什么区别?
  13. 记一次学习爬取豆瓣数据于Excel表的爬虫
  14. u3d计算向量间夹角
  15. 软件工程复习笔记 类图
  16. 安装部署rabbitmq报错——已解决
  17. C语言经典一百题(六)用*号输出字母C的图案。
  18. @Cacheable和@CacheEvict的学习使用
  19. SRP-PHAT综述
  20. C语言经典题目:有5个人坐在一起,问他们分别多少岁?

热门文章

  1. python中的标准输入设备_从MIDI设备获取输入(Python)
  2. php脚本执行时间设置
  3. 中关村十大AI研究院|盘点
  4. 官方消息:即将开始退钱
  5. java系统架构设计,2022最新
  6. Webdriver - webdriver hangs when get or click
  7. 《蔡康永的201堂情商课(完结)》学习
  8. “互联网+”大学生创新创业大赛概述
  9. 神州战神电脑关闭触摸板
  10. 2017电子设计大赛-光电科技协会板球控制系统