30求调
查看原帖
30求调
1206518
Nervegas楼主2024/7/7 13:43
#include<bits/stdc++.h>
using namespace std;
const int maxn = 500010;
struct node{
	int to,nxt;
}e[maxn * 2],ee[maxn * 2];
int n,m;
stack<int> S;
int dfn[maxn],low[maxn],sccno[maxn],dfs_clock,scc_cnt,head[maxn],cnt;
int h[maxn],cnt1;//重构图,缩点; 
int inv[maxn];//入度 
bool vis[maxn];//标记,防止重边;
int size[maxn];//记录每个连通分量有多少点; 
void add(int u,int v){
	e[++cnt].to = v;
	e[cnt].nxt = head[u];
	head[u] = cnt;
}
void add1(int u,int v){
	ee[++cnt1].to = v;
	ee[cnt1].nxt = h[u];
	inv[v]++;
	h[u] = cnt1;
}
void tarjan(int u){
	dfn[u] = low[u] = ++dfs_clock;
	S.push(u);
	for(int i = head[u] ; i ; i = e[u].nxt){
		int v = e[i].to;//遍历点 
		if(!dfn[v]){
			tarjan(v);
			low[u] = min(low[u],low[v]); 
		}
		else if(!sccno[v]){
			low[u] = min(low[u],dfn[v]);
		}
	}
	if(low[u] == dfn[u]){
		scc_cnt++;//找到连通分量
		while(true){
			int v = S.top();
			S.pop();
			sccno[v] = scc_cnt;
			size[scc_cnt]++; 
			if(v == u){
				break;
			} 
		} 
	}
}
int main(){
	ios::sync_with_stdio(0),cin.tie(0);
	cin >> n >> m;
	for(int i = 1 ; i <= m ; i++){
		int v,u;
		cin >> v >> u; 
		add(v,u);
	}
	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 ; j = e[i].nxt){
			if(sccno[i] == sccno[e[j].to] || vis[sccno[e[j].to]]){//边被标记,在一个联通分量; 
				continue;
			}
			add1(sccno[i],sccno[e[j].to]);
			vis[sccno[e[j].to]] = true;//标记; 
		}
		for(int k = head[i] ; k ; k = e[i].nxt){
			vis[sccno[e[k].to]] = false;
		}
	}
	int tot = 0;
	bool rt = true;
	for(int i = 1 ; i <= scc_cnt ; i++){
		if(!inv[i]){
			tot++;//统计入度为0的点 
		}
		if(inv[i] || size[i] > 1){
			continue;
		}
		if(rt){
			bool flag = true;
			for(int j = h[i] ; j ; j = ee[j].nxt){
				if(inv[ee[j].to] <= 1){
					flag = false;
					break;
				}
			}
			if(flag){
				tot--;
				rt = false;
			}
		}
	}
	double ans = (double)(n - tot) / n; 
	printf("%.6lf",ans);
	return 0;
}
2024/7/7 13:43
加载中...