首页 > 其他分享 >P4819 题解

P4819 题解

时间:2023-07-09 18:44:17浏览次数:58  
标签:个点 int 题解 入度 ++ MAXN low P4819

题意简述

\(n\) 个居民中有一名杀手,有些居民知道其他一些人的身份是杀手还是平民,该类条件共 \(m\) 条。现在警方要询问一些居民来获得其他人的信息,要求在能够从已知条件推断出杀手是谁的前提下询问尽可能少的人。然而每个居民是杀手的概率都是 \(\frac{1}{n}\),因此警方询问的居民中可能就有杀手,从而被杀。求询问最少人的情况下警察生还的几率。

题目分析

很明显,题目的条件可以构成一个 \(n\) 个顶点、\(m\) 条边的有向图 \(G=(V,E)\)。因此问题转换为:在该有向图中找到最少的点,使得从这些点出发可以到达所有 \(n\) 个点或者其中的 \(n-1\) 个点。而之所以到达其中的 \(n-1\) 个点就满足题意,是因为当“知道” \(n-1\) 个点的“身份”时,杀手只可能是剩下的一个点或者在这 \(n-1\) 个点其中。因此设答案取的点的点集为 \(V'\subseteq V\),假设 \(G\) 是一个 DAG,则满足:令 \(A=\{j\in V |\exists i \in V',(i,j) \in E\}, |A|=n-1\) 或 \(n\)

显然,为了满足最优性,点集 \(V'\) 中的所有点的入度为 0(请自行思考原因)。不过,因为 \(G\) 不一定是一个 DAG,所以我们可以对其进行 tarjan 强连通分量缩点,这里将其作为基础知识不再赘述,如果不了解其过程及原理请查阅相关资料:【洛谷日报第 27 期】初探tarjan算法(求强连通分量)

我们再来讨论一下 \(V'\) 的求法。如果存在 1 个点满足入度为 0 并且该点连向的所有点的入度都大于 1(也就是从其他入度为 0 的点出发可以到达),那么就说明可以不将这个“无用”的点放入 \(V'\) 。注意,该类点如果有多个则只能去除一个,其他的点仍需要放入 \(V'\) 。综上,原题的答案就是 \(\frac{|V'|}{n}\),时间复杂度为 \(O(n+m)\)。

代码实现

#include<bits/stdc++.h>
using namespace std;
const int MAXN=100010,MAXM=300010;
int m,n,a,b,ans;
int nt[MAXM],hd[MAXN],v[MAXM],tot;
int nt2[MAXM],hd2[MAXN],v2[MAXM],tot2,ru[MAXN];
int dfn[MAXN],low[MAXN],C[MAXN],cnt,num,stk[MAXN],top,sz[MAXN];
bool ins[MAXN];
void add(int x,int y)
{
  v[++tot]=y;
  nt[tot]=hd[x];
  hd[x]=tot;
}
void add2(int x,int y)
{
  v2[++tot2]=y;
  nt2[tot2]=hd2[x];
  hd2[x]=tot2;
  ru[y]++;
}//建新图 
inline void tarjan(int x)//tarjan 求强连通分量 
{
  dfn[x]=low[x]=++cnt;
  stk[++top]=x;
  ins[x]=1;
  for(int i=hd[x]; i; i=nt[i])
  {
    int y=v[i];
    if(!dfn[y])
    {
      tarjan(y);
      low[x]=min(low[x],low[y]);
    }
    else if(ins[y])
      low[x]=min(low[x],dfn[y]);
  }
  if(low[x]==dfn[x])
  {
    int y;
    num++;
    do
    {
      y=stk[top--];
      ins[y]=0;
      C[y]=num;
      sz[num]++;
    }
    while(x!=y);
  }
}
bool pd(int x)//判断该点是否满足入度为 0 并且连向的所有点的入度都大于1 
{
  if(!ru[x]&&sz[x]==1)
    for(int i=hd2[x]; i; i=nt2[i])
    {
      int y=v2[i];
      if(ru[y]==1)
        return 0;
    }
  return !ru[x]&&sz[x]==1;
} 
int main()
{
  scanf("%d%d",&n,&m);
  for(int i=1; i<=m; i++)
  {
    scanf("%d%d",&a,&b);
    add(a,b);
  }
  for(int i=1; i<=n; i++)
    if(!dfn[i])
      tarjan(i);
  memset(ins,0,sizeof ins);
  for(int x=1; x<=n; x++)//缩点 
  {
    for(int i=hd[x]; i; i=nt[i])
    {
      int y=v[i];
      if(C[x]!=C[y]&&!ins[C[y]])
      {
        ins[C[y]]=1;
        add2(C[x],C[y]);
      }
    }
    for(int i=hd[x]; i; i=nt[i])
    {
      int y=v[i];
      ins[C[y]]=0;
    }//注意该题缩点不能有重边 
  }
  for(int i=1; i<=num; i++)
    if(!ru[i])
      ans++;//初始答案点集就是缩点后入度为 0 的点。 
  for(int i=1; i<=num; i++)
    if(pd(i))
    {
      ans--;
      break;
    }//去掉“无用点”。 
  printf("%.6lf",(double)(n-ans)/n);
  return 0;
}

标签:个点,int,题解,入度,++,MAXN,low,P4819
From: https://www.cnblogs.com/hadtsti/p/P4819-solution.html

相关文章

  • redis雪崩问题解决
    缓存雪崩出现的场景缓存服务器宕机,没有设置持久化介绍:缓存服务器宕机,没有设置持久化,导致缓存数据全部丢失,请求全部转发到数据库,造成数据库短时间内承受大量请求而崩掉。缓存集中失效缓存的key设置了相同的过期时间,导致在某一时刻,大量的key同时失效,请求全部转发到数据库,造成......
  • gym 102994M Travel Dream 题解
    给定带权无向图,求最大\(k\)元环。\(n,m\leq300,3\leqk\leq10\),无重边。把\(k=3\)判掉,可以\(O(m^2)\)轻松解决。把\(k\)元环拆成长度为\(\dfrac{k}{2}-1\)的链\(+\)长度\(k-\dfrac{k}{2}-1\)的链\(+\)连接两条链的两条边。(长度指边的个数)问题:两条链需要无......
  • 「NOIP 模拟赛 20230709」T3 - 与行星相会 题解
    题目大意原题有一个\(n\timesn\)的点阵,将相邻的点连边得到一个\((n-1)\times(n-1)\)的网格。\(q\)次操作,每次删掉一条边,求删掉后边两端的点是否仍在一个连通块内。强制在线。题解显然,由于对偶图的性质,原图的一个割对应对偶图中的一个环,所以只需要删掉一条边时在对偶图中......
  • 寻找页码题解
    首先看题目,我也不知道这一题的出处。。。。在网上找了很久也没找到。。。题目描述从第1页开始,页码组成的数字序列如下:123..101112..99100101...这串序列又被称之为连写数。给定一个0到9之中的单独一位数字a,请问在这串序列中,第k次出现a,是在哪一页上?以数码1为例,第......
  • 华泰证券FINTECH决赛第二题题解
    被第二题搞得坐牢2个半小时,在最后10分钟才确定推出的求和公式没问题,是除法取模不规范导致求解有偏差,只能说菜是原罪。这里贴一下赛后修改的代码,希望能对列位有些帮助,欢迎巨佬指导。思路:分奇偶讨论固定长度下伪回文串的数量,定义长度为\(n\)的伪回文串的数量为\(a_{n}\):(1)\(n\)......
  • P7112 题解
    题意简述模板题,求一个\(n\timesn(n\le600)\)的方阵的行列式模一个正整数\(p(1\lep\le10^9+7)\)的值(\(p\)不一定是质数)。题目分析这个题的最终代码其实很简单,重点在于过程。说实话,我在做这个题之前也就只知道个行列式的定义,只会暴力硬算。做了这个题才了解了行列式有那......
  • 关于Azure-平台-Redhat-Linux-服务器时间同步的问题解决
    首先说明一下,关于Azure平台中国区,是没有RedhatLinux系统镜像的于是笔者这边是通过在Windows系统 Hyper-V管理器中安装完Redhat8.x操作系统后,最后将系统磁盘转换成转换为VHD格式然后经过一系列操作、最终在Azure平台上形成了自己的并且加固过的RedHatEnterpriseLinuxre......
  • 【题解】 [APIO2007] 动物园
    目录题目链接原题描述题目描述输入格式输出格式样例#1样例输入#1样例输出#1样例#2样例输入#2样例输出#2提示题意概括思路历程1.与环相关2.设计状态代码实现题目链接原题描述[APIO2007]动物园题目描述新建的圆形动物园是亚太地区的骄傲。圆形动物园坐落于太平洋的一个......
  • 洛谷题解——【模板】堆
    题目链接:【模板】堆【模板】堆题目描述给定一个数列,初始为空,请支持下面三种操作:给定一个整数\(x\),请将\(x\)加入到数列中。输出数列中最小的数。删除数列中最小的数(如果有多个数最小,只删除\(1\)个)。输入格式第一行是一个整数,表示操作的次数\(n\)。接下来\(n\)......
  • 并发网络周测题解释版
    并发网络周测题【一】理论篇1.简述OSI七层协议OSI七层协议(OpenSystemsInterconnection)是一种用于计算机网络通信的参考模型。该模型将网络通信过程分解为七个不同的层次,每个层次负责特定的功能和任务,这有助于网络设备和应用程序之间的协作和互操作性。【1】物理层(Physica......