[题解]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));
}

 

少问一次

 

posted @ 2019-11-01 15:13  羊肉汤泡煎饼  阅读(179)  评论(0编辑  收藏  举报