luogu4819 杀人游戏 题解

update 2022.2.9 修改了代码

不妨假设平民为白点,杀手为黑点,认识的关系为一条有向边。

求不访问黑点并且知道黑点的最小代价。

若有 \(n\) 个点,显然每个点为黑的概率为 \(\frac{1}{n}\)

而每访问一个白点,都能得知与它出边相连的点的颜色。

考虑强连通分量。

不难发现,对于每个强连通分量,只要以概率增加 \(\frac{1}{n}\) 为代价访问其中一个点,就能得知整个强连通分量的颜色情况。。

所以求出强连通分量后进行缩点,我们就得到了一个 DAG。

为了减少总访问次数,访问入度不为 0 的 SCC 是不划算的。

简单证明:设缩点后存在 \((x \rightarrow y)\) 的边,则访问完 \(x\) 中所有的点后,必定能知道 \(y\) 中一个点的信息,所以对于 \(y\),不需要增加 \(\frac{1}{n}\) 的访问代价。

所以设缩点后入度为 0 的点的数量为 \(s\),则访问到黑点的概率为 \(\frac{s}{n}\),答案为 $ $。

 

考虑只含一个点的 SCC,设其为 \(c\),若其入度为 0,且其能够到达的点的入度均大于 1,那么若最后访问 \(c\),整张图的情况已经被确定了。若未找到黑点,则 $ c$ 为黑点。如果包含超过 1 个节点,那么必须再访问它再能确定黑点。这样可以减少一次访问,且对于任意图,能且仅能减少一次。

所以若存在 \(c\),令 \(s-1\) 即可。

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int N=1e5+6;
int n, m, k, num, ans, dfn[N], low[N], st[N];
int scc, c[N], deg[N], sz[N];
int cnt, h[N], ver[3*N], nxt[3*N];
int tc, hc[N], vc[3*N], nc[3*N];
bool v[N];
void add(int x,int y) { ver[++cnt]=y, nxt[cnt]=h[x], h[x]=cnt; }
void adc(int x,int y) { vc[++tc]=y, nc[tc]=hc[x], hc[x]=tc; }
void tarjan(int x) {
    dfn[x]=low[x]=++num, st[++k]=x;
    for(int i=h[x];i;i=nxt[i]) {
        int y=ver[i];
        if(!dfn[y]) {
            tarjan(y);
            low[x]=min(low[x],low[y]);
        } else if(!c[y]) low[x]=min(low[x],dfn[y]);
    }
    if(dfn[x]==low[x]) {
        ++scc;
        do y=st[k--], c[y]=scc, ++sz[scc]; while(x!=y);
    }
}
bool f(int x) {
    if(deg[x]||sz[x]!=1) return 0;
    for(int i=hc[x];i;i=nc[i]) if(deg[vc[i]]==1) return 0;
    return 1;
}
int main() {
    scanf("%d%d",&n,&m);
    for(int i=1,x,y;i<=m;++i) scanf("%d%d",&x,&y), add(x,y);
    for(int i=1;i<=n;++i) if(!dfn[i]) tarjan(i);
    for(int x=1;x<=n;++x) {
    	memset(v,0,sizeof(v));
		for(int i=h[x];i;i=nxt[i]) {
        	int y=ver[i];
        	if(c[x]!=c[y]&&!v[c[y]]) {
				v[c[y]]=1, ++deg[c[y]], adc(c[x],c[y]);
			}
		}
    }
    for(int i=1;i<=scc;++i) if(!deg[i]) ++ans;
    for(int i=1;i<=scc;++i) if(f(i)) { --ans; break; }
    printf("%.6lf\n",1.0*(n-ans)/n);
}

luogu4819 杀人游戏 题解
https://yozora0908.github.io/2021/lg4819-solution/
作者
yozora0908
发布于
2021年9月20日
许可协议