我写了Tarjan+判断联通分量,但36pts
查看原帖
我写了Tarjan+判断联通分量,但36pts
782210
Yu_Chengxuan楼主2024/8/10 14:42
#include <bits/stdc++.h>
using namespace std;

inline int read() {
	int x=0,f=1;
	char ch=getchar();
	while (ch<'0'||ch>'9') {
		if (ch=='-') f=-1;
		ch=getchar();
	}
	while (ch>='0'&& ch<='9') {
		x=x*10+ch-48;
		ch=getchar();
	}
	return x*f;
}
const int maxn = 1e5 + 10;
vector<int> e[maxn];
vector<int> g[maxn];
int dfn[maxn],low[maxn],scc[maxn],ins[maxn],cf[maxn],siz[maxn],check[maxn],tot,cnt;
stack<int> s;

void tarjan(int u,int fa){
	dfn[u]=low[u]=++tot;
	ins[u]=1;
	s.push(u);
	bool flag=0;
	for (auto i:e[u]){
		int v=i;
		if (v==fa && !flag){
			flag=1;
			continue;
		}
		if (!dfn[v]){
			tarjan(v,u);
			low[u]=min(low[u],low[v]);
		}
		else if(ins[v]){
			low[u]=min(low[u],dfn[v]);
		}
	}
	if (dfn[u]==low[u]){
		cnt++;
		int x=-1;
		do{
			x=s.top();
			scc[x]=cnt;
			ins[x]=0;
			s.pop();
			siz[cnt]++;
		}while(x!=u);
	}
}

signed main() {
	int n=read(),m=read();
	for (int i=1;i<=m;i++){
		int u=read(),v=read();
		e[u].push_back(v);
	}
	for (int i=1;i<=n;i++){
		if (!dfn[i]){
			tarjan(i,0);
		}
	}
	for (int u=1;u<=n;u++){
		for (int v:e[u]){
			if(scc[u]==scc[v] || check[scc[v]]){
				continue;
			}
			g[scc[u]].push_back(scc[v]);
			check[scc[v]]=true;
			cf[scc[v]]++;
		}
		for (int v:e[u]){
			 check[scc[v]]=false;
		} 
	}
	int x=0;		
	for(int i=1;i<=cnt;i++){
		if (!cf[i]){
			x++;
		}		
		if(siz[i]!=1 || cf[i]) continue;	
		bool flag=0;
		for(auto j:g[i]){
			if(cf[j]>=2){
			    flag=1;
			    break;
			}
		}
		if(flag){
			x--;
			break;
		}
	}
	double ans;
	ans = 1.0*(n-x)/n;
	printf("%.6lf",ans);
}
2024/8/10 14:42
加载中...