P4819题解
题意简述
题目分析
很明显,题目的条件可以构成一个
显然,为了满足最优性,点集
我们再来讨论一下
代码实现
#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; }
本文应该讲得挺清楚了,管理大大就给过了吧
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现