1 solutions

  • 2
    @ 2025-7-2 20:44:26

    题意

    给张有向图,求多少个点能被所有点走到。

    思路

    首先很容易看出来,当整张图强连通时,每个点都是明星。

    然后考虑其他情况,当整张图被分为强连通分量时,缩点后的新图是 DAG[1] 嘛,所以出度为 00 的那个强连通分量的大小就是明星数量。

    但是要注意,整张图不一定连通,换句话说,出度为 00 的强连通分量的个数大于 11,那么就没有明星了。(整张图被分为几个子图)

    代码

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N = 1e4 + 5,M = 5e4 + 5;
    int n,m,tot,dfn[N],low[N],cnt,a[N],f[N];
    bool is[N],f2[N];
    vector<int> g[N],root,g2[N];
    void dfs(int u){
    	dfn[u] = ++tot,low[u] = dfn[u];
    	for (int v : g[u]){
    		if (!dfn[v])	dfs(v);
    	}
    }
    stack<int> s;
    void tarjan(int u){
    	s.push(u);
    	f[u] = 1;
    	is[u] = 1;
    	for (int v : g[u]){
    		if (!f[v])	tarjan(v);
    		if (is[v])	low[u] = min(low[u],low[v]);
    	}
    	if (dfn[u] == low[u]){
    		cnt++;
    		int sum = 1;
    		f[u] = cnt;
    		while (s.top() != u){
    			sum++;
    			f[s.top()] = cnt;
    			is[s.top()] = 0;
    			s.pop();
    		}
    		a[cnt] = sum;
    		s.pop();
    		is[u] = 0;
    	}
    }
    int main(int argc, char **argv){
    	cin >> n >> m;
    	for (int i = 1;i <= m;i++){
    		int u,v;
    		cin >> u >> v;
    		g[u].push_back(v);
    	}
    	for (int i = 1;i <= n;i++){
    		if (!dfn[i])	dfs(i),root.push_back(i);
    	}
    	for (int i : root)	tarjan(i);
    	for (int i = 1;i <= n;i++){
    		for (int v : g[i]){
    			if (f[i] != f[v])	g2[f[i]].push_back(f[v]),f2[f[i]] = 1;
    		}
    	}
    	int ans = 0;
    	for (int i = 1;i <= cnt;i++){
    		if (!f2[i] && ans){
    			cout << 0;
    			return 0;
    		}else if (!f2[i])	ans = a[i];
    	}
    	cout << ans;
    	return 0;
    }
    
    

    1. 有向无环图 ↩︎

    • 1

    Information

    ID
    420
    Time
    1000ms
    Memory
    128MiB
    Difficulty
    7
    Tags
    # Submissions
    56
    Accepted
    13
    Uploaded By