版权声明:版权声明:本文为博主原创文章,未经博主允许不得转载,欢迎添加友链。 https://blog.csdn.net/zzk_233/article/details/82942896
根据题意只要找出有多少个不连通的集合就可以了。。但是在判定的时候有环的话会有点麻烦,所以先缩点,在dfs。
但是如果有一个点它的所有连的点不止它一个入度的话 ,而且这个点的入度为0,那么最后剩它的时候就不用问了。
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
struct node
{
int to;
int nxt;
}edge[300005],edge1[300005];
int head[100005],head1[100005];
int cnt=1,ans,cot=1,gs[100005];
void init()
{
memset(head,-1,sizeof(head));
memset(head1,-1,sizeof(head1));
}
void add(int from,int to)
{
edge[cnt].to=to;
edge[cnt].nxt=head[from];
head[from]=cnt++;
}
void added(int from,int to)
{
edge1[cot].to=to;
edge1[cot].nxt=head1[from];
head1[from]=cot++;
}
int dfn[100005];
int low[100005];
int srcnt;
int pos[100005];
int srans[100005];
int deep=0;
int top;
int stackk[100005];
int used[100005];
int out[100005],outt[100005];
void tarjan(int rt)
{
dfn[rt] = low[rt] = ++deep;
stackk[++top] = rt;
for(int i = head[rt];i != -1;i = edge[i].nxt)
{
int to = edge[i].to;
if(dfn[to] == 0)
{
tarjan(to);
low[rt] = min(low[rt],low[to]);
}else if(pos[to] == 0)
{
low[rt] = min(low[rt],dfn[to]);
}
}
if(low[rt] == dfn[rt])
{
int v = 0;
int t = 0;
srcnt++;
while(v != rt)
{
v = stackk[top];
top--;
t++;
pos[v] = srcnt;
}
srans[srcnt] = t;
}
}
void dfs(int u,int ttt)
{
used[u]=ttt;
for(int i=head1[u];i!=-1;i=edge1[i].nxt)
{
int to=edge1[i].to;
dfs(to,ttt);
}
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
init();
for(int i=1;i<=m;i++)
{
int a,b;
scanf("%d%d",&a,&b);
add(a,b);
outt[b]++;
}
for(int i=1;i<=n;i++)
{
if(!dfn[i])
{
tarjan(i);
}
}
for(int i=1;i<=n;i++)
{
for(int j=head[i];j!=-1;j=edge[j].nxt)
{
int to=edge[j].to;
if(pos[i]!=pos[to])
{
added(pos[i],pos[to]);
out[pos[to]]++;
}
}
}
for(int i=1;i<=srcnt;i++)
{
if(!out[i])dfs(i,i);
}
for(int i=1;i<=srcnt;i++)
{
if(used[i]==i)
{
ans++;
}
gs[used[i]]++;
}
int flag=0;
for(int i=1;i<=n;i++)
{
if(!outt[i])
{
for(int j=head[i];j!=-1;j=edge[j].nxt)
{
int to=edge[j].to;
if(outt[to]==1)
{
flag=1;break;
}
}
if(!flag)
{
ans--;break;
}else
{
flag=0;
}
}
}
double tt=(double)(n-ans)/(double)n;
printf("%.6lf",tt);
return 0;
}