48分求助
查看原帖
48分求助
232838
huangkx楼主2021/8/19 09:58

RT
可能代码复杂了一点,思路就是先缩点,再看是不是所有点都能到某个点,如果能答案就加上这个点的权值(强连通分量的大小)。
请大佬指教。

#include <bits/stdc++.h>
using namespace std;
int n, m;
int u, v;
vector <int> g[10005];
vector <int> rg[10005];
vector <int> ng[10005];
bool vis[10005];
int s[10005], top;
int c[10005], sum;
int val[10005];
int in[10005];
int ans;
void dfs(int u)
{
	if(vis[u] == true) return;
	vis[u] = true;
	for(int i=0; i<g[u].size(); i++){
		int v = g[u][i];
		dfs(v);
	}
	s[++top] = u;
}
void rdfs(int u)
{
	if(c[u] != 0) return;
	c[u] = sum;
	for(int i=0; i<rg[u].size(); i++){
		int v = rg[u][i];
		rdfs(v);
	}
}
void Kosaraju()
{
	top = 0;
	sum = 0;
	for(int i=1; i<=n; i++){
		vis[i] = false;
		c[i] = 0;
	}
	for(int i=1; i<=n; i++) dfs(i);
	for(int i=top; i>=1; i--){
		if(c[s[i]] == 0){
			sum++;
			rdfs(s[i]);
		}
	}
}
void shrink()
{
	for(int i=1; i<=n; i++){
		val[c[i]]++;
		for(int j=0; j<g[i].size(); j++){
			int u, v;
			u = c[i];
			v = c[g[i][j]];
			if(u == v) continue;
			ng[u].push_back(v);
			in[v]++;
		}
	}
}
void ndfs(int u, int k)
{
	k++;
	if(k == sum) ans += val[u];
	for(int i=0; i<ng[u].size(); i++){
		int v = ng[u][i];
		ndfs(v, k);
	}
}
int main()
{
	scanf("%d%d", &n, &m);
	for(int i=1; i<=m; i++){
		scanf("%d%d", &u, &v);
		g[u].push_back(v);
		rg[v].push_back(u);
	}
	Kosaraju();
	shrink();
	for(int i=1; i<=sum; i++){
		if(in[i] == 0){
			ndfs(i, 0);
		}
	}
	printf("%d", ans);
	return 0;
}
2021/8/19 09:58
加载中...