[中山市选] 杀人游戏

来源:互联网 发布:智能电视聊天软件 编辑:程序博客网 时间:2024/04/29 07:33

原题:中山市选 2011 杀人游戏

方法:Tarjan 


program kill_game;const maxn=100000; maxm=300000;type    link=^node; node=record x:longint; next:link;end; procedure push(var x:link; const t:longint);var p:link;begin    new(p);    p^.x:=t; p^.next:=x; x:=p;end; var low,dfn,pre,ss,bl:array[1..maxn]of longint;    v:array[1..maxn]of boolean;    ge:array[1..maxn]of link;    cnt,tt,k:longint; function min(const i,j:longint):longint;begin    if i<j then exit(i); exit(j);end;procedure tarjan(i:longint);var j:longint; p:link;begin    inc(cnt); dfn[i]:=cnt; low[i]:=cnt;    v[i]:=true; inc(tt); ss[tt]:=i;    p:=ge[i]; while p<>nil do begin    j:=p^.x;    if dfn[j]=0 then begin tarjan(j); low[i]:=min(low[i],low[j]); end else    if v[j] then low[i]:=min(low[i],dfn[j]);    p:=p^.next;    end;    if dfn[i]=low[i] then begin    inc(k); j:=i+1;    while j<>i do begin        j:=ss[tt];dec(tt);        v[j]:=false;        bl[j]:=k;    end;    end;end; var n,m,i,x,y,ans:longint; p:link; flag:boolean; begin    readln(n,m); ans:=0;    for i:=1 to m do begin readln(x,y);push(ge[x],y);end;    for i:=1 to n do if dfn[i]=0 then tarjan(i);    for i:=1 to n do begin    p:=ge[i];while p<>nil do begin        if bl[i]<>bl[p^.x] then        if pre[bl[p^.x]]=0 then pre[bl[p^.x]]:=bl[i] else        if pre[bl[p^.x]]<>bl[i] then pre[bl[p^.x]]:=-1;        p:=p^.next;    end;    end;    for i:=1 to k do if pre[i]=0 then inc(ans);    for i:=1 to n do if pre[bl[i]]=0 then begin    flag:=true; p:=ge[i];    while flag and (p<>nil) do begin        if bl[i]=bl[p^.x] then flag:=false;        if pre[bl[p^.x]]<>-1 then flag:=false;        p:=p^.next;    end;    if flag then break;    end;    dec(ans,ord(flag));    writeln((n-ans)/n:0:6);end.