[题解]luogu_P4819_杀人游戏(缩点
首先需要看懂题目,反正就是要求最少问几个人......,缩点直接搞
然而唯一不同的是可能问完n-1个人都不是,最后的人就不用问了,这种情况出现需要有一个人单独出现,并且没有其他点只能通过他获取信息,也就是存在siz[x]=1,indegree[y]!=1,那样可以
#include<bits/stdc++.h> using namespace std; const int maxn=100009; int n,m,tim; struct node{ int v,nxt,u; }e[maxn*3],e2[maxn*3]; int head[maxn],cnt,hd[maxn],cnt2; inline void add(int u,int v){ e[++cnt].v=v;e[cnt].u=u;e[cnt].nxt=head[u];head[u]=cnt; } inline void add2(int u,int v){ e2[++cnt2].v=v;e2[cnt2].nxt=hd[u];hd[u]=cnt2; } int low[maxn],dfn[maxn],st[maxn],top,id[maxn],siz[maxn],vis[maxn]; void tarjan(int x){ dfn[x]=low[x]=++tim; st[++top]=x; vis[x]=1; for(int i=head[x];i;i=e[i].nxt){ int y=e[i].v; if(!dfn[y]){ tarjan(y); low[x]=min(low[x],low[y]); } else if(vis[y])low[x]=min(low[x],low[y]); } if(low[x]==dfn[x]){ int y; while(y=st[top--]){ id[y]=x;vis[y]=0; if(x==y)break; siz[x]+=siz[y]; } } } int in[maxn]; int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)siz[i]=1; for(int i=1,u,v;i<=m;i++){ scanf("%d%d",&u,&v); add(u,v); } for(int i=1;i<=n;i++)if(!dfn[i])tarjan(i); for(int i=1;i<=m;i++){ if(id[e[i].u]!=id[e[i].v])add2(id[e[i].u],id[e[i].v]),in[id[e[i].v]]++; } int ans=0,fl=0; for(int i=1;i<=n;i++) if(id[i]==i&&in[i]==0){ ans++; if(!fl&&siz[i]==1){ int pd=0; for(int j=hd[i];j;j=e2[j].nxt){ int y=e2[j].v; if(in[y]==1)pd=1; } if(!pd)fl=1; } } if(fl)ans--; printf("%.6lf\n",1.0-(1.0*ans)/(1.0*n)); }
少问一次