Kill the game (tarjan thinking good title)

P4819 [Zhongshan election] to kill the game

analysis:

Analysis of this problem start with a simple: if one strand is: 1-> 2-> 3-> 4
directly to check the degree of 0: Knowing 1, 2 to know, if the killer is 2, is ended.
Otherwise, go check 2 (!! 2 is not known because the killer so this step is not required to spend slain risk)
and so on.
The final answer is 1- (1 / n) * ans
a chain only need to check a 0-degree point, then if there is an isolated ring it?
Obviously any need to check the ring to a point. It can be used tarjan retrusion points to find the point of 0 degree.
This question but there are many other pit:
EG: 100 0
if individuals are checked over before 99, the first 100 people you can not checked
think about when you can not check: When a 0-degree point, and it's even All points penetration is not 1 (that is to say the other points can be found through another point 0-degree)
and its siz == 1 (is isolated dots, or rings have a check point)
Laid sentenced to click.

#include<bits/stdc++.h>
using namespace std;
#define ri register int
#define N 100005
int n,m,dfn[N],low[N],stk[N],flag[N],bel[N],ru[N],Ti=0,tot=0,top=0,siz[N];
vector<int> e[N];
vector<int> h[N];
void tarjan(int u)
{
    dfn[u]=low[u]=++Ti;
    stk[++top]=u; flag[u]=1;
    for(ri i=0;i<e[u].size();++i){
        int v=e[u][i];
        if(!dfn[v]){
            tarjan(v);
            low[u]=min(low[u],low[v]);
        }
        else if(flag[v]) low[u]=min(low[u],dfn[v]);
    }
    if(dfn[u]==low[u]){
        tot++;
        do{
            int tmp=stk[top];
            flag[tmp]=0; bel[tmp]=tot; siz[tot]++;
        }while(stk[top--]!=u);
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    int a,b;
    for(ri i=1;i<=m;++i) scanf("%d%d",&a,&b),e[a].push_back(b);
    for(ri i=1;i<=n;++i) if(!dfn[i]) tarjan(i);
    for(ri i=1;i<=n;++i){
        for(ri j=0;j<e[i].size();++j){
            int v=e[i][j];
            if(bel[i]==bel[v]) continue;
            h[bel[i]].push_back(bel[v]); ru[bel[v]]++;
        }
    }
    int fl=0,ans=0;
    for(ri i=1;i<=tot;++i)
    if(!ru[i]){
        ans++;
        if(fl || siz[i]>1) continue;
        fl=1;
        for(ri j=0;j<h[i].size();++j)
        if(ru[h[i][j]]<2) { fl=0; break;} 
    }
    //printf("%d\n",ans-fl);
    printf("%.6lf\n",(1-(1.0/n)*(double)(ans-fl)));
    return 0;
}
/*
6 5
1 2
1 3
4 2
5 2
6 2

4 3
1 2
2 3
3 4
*/
View Code

 

Guess you like

Origin www.cnblogs.com/mowanying/p/11778710.html