BZOJ 2438 杀人游戏(强连通分量)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2438

题意:一位冷血的杀手潜入某村庄,并假装成 平民。警察希望能在 N 个人里面,查出谁是杀手。 警察能够对每一个人进行查证,假如查证的对象是平民,他会告诉警察,他认识的人, 谁是杀手, 谁是平民。 假如查证的对象是杀手, 杀手将会把警察干掉。 现在警察掌握了每一个人认识谁。 每一个人都有可能是杀手,可看作他们是杀手的概率是相同的。 问:根据最优的情况,保证警察自身 安全并知道谁是杀手的概率最大是多少?

思路:首先,求一次强连通分量SCC。那么 在一个SCC里知道了一个其他就都知道了。然后重新建图就得到一个有向无环图DAG。在这个DAG里,我们只要去询问那些入度为0的点即可。但是,有一种 特殊情况,就是我们假设知道了n-1个人是或不是杀手,那么另外那一个人即便他的入度为0也是不需要询问的。这样的人存不存在我们只需要判断它的孩子的入 度即可。若它的所有孩子的入度均大于1,也就是它的所有孩子都可由其他点遍历到,那么这个点就是不用询问的。而且这样的点即使有多个也只能算一次。

vector<int> g[N];
int dfn[N],low[N],id,num,color[N],size[N],visit[N];
stack<int> St;

void DFS(int u)
{
    dfn[u]=low[u]=++id; St.push(u);
    int i,v;
    FOR0(i,SZ(g[u]))
    {
        v=g[u][i];
        if(!dfn[v]) DFS(v),upMin(low[u],low[v]);
        else if(!visit[v]) upMin(low[u],dfn[v]);
    }
    if(dfn[u]==low[u])
    {
        num++;
        do
        {
            v=St.top(); St.pop();
            visit[v]=1;
            color[v]=num;
            size[num]++;
        }while(u!=v);
    }
}

int n,m;
set<i64> S;
vector<int> G[N];
int ind[N];

int main()
{
    RD(n,m);
    int i,j,x,y;
    FOR1(i,m) RD(x,y),g[x].pb(y);
    FOR1(i,n) if(!visit[i]) DFS(i);
    i64 temp;
    FOR1(i,n) FOR0(j,SZ(g[i]))
    {
        x=g[i][j];
        if(color[x]==color[i]) continue;
        temp=(i64)color[i]*(n+1)+color[x];
        if(S.find(temp)!=S.end()) continue;
        S.insert(temp);
        G[color[i]].pb(color[x]);
        ind[color[x]]++;
    }
    double ans=1,det=1.0/n;
    int flag=1;
    FOR1(i,num) if(!ind[i])
    {
        if(size[i]==1)
        {
            FOR0(j,SZ(G[i])) if(ind[G[i][j]]==1) break;
            if(flag&&j>=SZ(G[i])) flag=0;
            else ans-=det;
        }
        else ans-=det;
    }
    PR(ans);
}

BZOJ 2438 杀人游戏(强连通分量),布布扣,bubuko.com

时间: 2024-12-11 14:11:41

BZOJ 2438 杀人游戏(强连通分量)的相关文章

BZOJ 2427 软件安装(强连通分量+树形背包)

题意:现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一些软件安装到一台磁盘容量为M计算机上,使得这些软件的价值尽可能大(即Vi的和最大).但是现在有个问题:软件之间存在依赖关系,即软件i只有在安装了软件j(包括软件j的直接或间接依赖)的情况下才能正确工作(软件i依赖软件j).幸运的是,一个软件最多依赖另外一个软件.如果一个软件不能正常工作,那么它能够发挥的作用为0. # include <cstdio> # include <cstri

bzoj 2438: [中山市选2011]杀人游戏 (强联通分量 Tarjan)

Description 一位冷血的杀手潜入 Na-wiat,并假装成平民.警察希望能在 N 个人里面,查出谁是杀手. 警察能够对每一个人进行查证,假如查证的对象是平民,他会告诉警察,他认识的人, 谁是杀手, 谁是平民. 假如查证的对象是杀手, 杀手将会把警察干掉. 现在警察掌握了每一个人认识谁. 每一个人都有可能是杀手,可看作他们是杀手的概率是相同的. 问:根据最优的情况,保证警察自身安全并知道谁是杀手的概率最大是多少? Input 第一行有两个整数 N,M. 接下来有 M 行,每行两个整数 x

BZOJ 2438: [中山市选2011]杀人游戏

Description 给你一个有向图,求至少询问多少次能够得到全部点的信息. Sol Tarjan + 强连通分量缩点 + 判断. 先缩点,如果我们知道了强连通分量里的任意一个点,我们就可以知道这些点的信息,和这些点所连接的其他点的信息,显然我们需要知道的就是缩点后入度为0的点. 然后还有最后一个入度为0的单点,并且他的所有儿子都能被其他节点访问,那么最后就可以直接推断出这个点,所以要删去. Code #include<cstdio> #include<stack> #inclu

【强连通分量+概率】Bzoj2438 杀人游戏

Description 一位冷血的杀手潜入 Na-wiat,并假装成平民.警察希望能在 N 个人里面,查出谁是杀手. 警察能够对每一个人进行查证,假如查证的对象是平民,他会告诉警察,他认识的人, 谁是杀手, 谁是平民. 假如查证的对象是杀手, 杀手将会把警察干掉. 现在警察掌握了每一个人认识谁. 每一个人都有可能是杀手,可看作他们是杀手的概率是相同的. 问:根据最优的情况,保证警察自身安全并知道谁是杀手的概率最大是多少? Sulotion 最优的询问对象是,把强连通分量缩成一个点(问其中一个可推

BZOJ 2438 中山市选2011 杀人游戏 Tarjan

题目大意:有n个人,其中一个是杀手,可以询问一些人,如果是杀手就会死,如果是平民,他会告诉你他认识的人中有谁是杀手有谁是平民 警告:数据有误,请谨慎提交! 易知如果我需要访问x个人,那么答案就是1-x/n 我们需要访问最少的人 如果我访问的人是平民,那么这个点所有的后继我都能知道 于是Tarjan缩点之后入度为零的点就是答案 但是还有一个问题 比如说这组样例 3 1 1 2 我访问了1,那么1和2是不是凶手我就都知道了 既然只有三个人,我知道1和2是不是凶手,那么3也一定知道 没必要去访问3 于

BZOJ 1093 最大半连通子图(强连通分量+树形DP)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1093 题意: 思路:(1)首先,强连通分量中的一个点若在最大半连通子图中,则必定整个连通分量中的点都在,因为都在还是满足半连通的性质而且使得节点数更多. (2)因此,求出强连通分量缩点,形成一个有向无环图,其实与树是差不多的.在这个图上DP一次即可,也就是找出最长链以及最长链的个数. vector<int> g[N],g1[N]; int n,m,mod; int dfn[N],lo

BZOJ 1924 所驼门王的宝藏(强连通分量+树形DP)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1924 题意: 思路:首先建立所有可达点之间的有向图.之后求强连通分量SCC,缩点重新构图.然后就是一个树,树形DP一下即可. int n,r,c; map<i64,int> mp; map<int,int> mp1,mp2; struct node { int x,y,op; }; node a[N]; int visit[N]; vector<int> V1

bzoj 1051 强连通分量

反建图,计算强连通分量,将每个分量看成一个点,缩点后的图是一个DAG,如果是一棵树,则根代表的连通分量的大小就是答案,否则答案为0. 收获: 图的东西如果不好解决,可以尝试缩点(有向图将每个强连通分量看成一个点,无向图将每个双连通分量看成一个点),缩点之后图就变成DAG或无向无环连通图,原本没有的一些性质就会在这是凸显出来,而且缩点的复杂度很低.

BZOJ 1179 Atm(强连通分量缩点+DP)

题目说可以通过一条边多次,且点权是非负的,所以如果走到图中的一个强连通分量,那么一定可以拿完这个强连通分量上的money. 所以缩点已经很明显了.缩完点之后图就是一个DAG,对于DAG可以用DP来求出到达每一个点的money最大值.具体实现我用的是bfs. 然后如果一个强连通分量内有酒馆,那么这个点就可以更新答案啦. # include <cstdio> # include <cstring> # include <cstdlib> # include <iost