返回顶部

Codeforces Round #490 (Div. 3) E. Reachability from the Capital (tarjan缩点)

  • 题意:有\(n\)个点,\(m\)条边,问你最少加多少条边,使得点\(s\)可以走到任何一个点.

  • 题解:我们直接用tarjan缩点后,判断除了\(s\)以外强连通分量的入度为\(0\)的个数即可.

  • 代码:

    #include <bits/stdc++.h>
    #define ll long long
    #define fi first
    #define se second
    #define pb push_back
    #define me memset
    #define rep(a,b,c) for(int a=b;a<=c;++a)
    #define per(a,b,c) for(int a=b;a>=c;--a)
    const int N = 1e6 + 10;
    const int mod = 1e9 + 7;
    const int INF = 0x3f3f3f3f;
    using namespace std;
    typedef pair<int,int> PII;
    typedef pair<ll,ll> PLL;
    ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;}
    ll lcm(ll a,ll b) {return a/gcd(a,b)*b;}
     
    int n,m,s;
    int dfn[N],low[N],timestamp;
    int stk[N],top;
    bool in_stk[N];
    int id[N],scc_cnt,sz[N];
    int din[N];
    
    vector<int> edge[N];
    
    void tarjan(int u){
        dfn[u]=low[u]=++timestamp;
        stk[++top]=u,in_stk[u]=true;
        for(auto w:edge[u]){
            if(!dfn[w]){
                tarjan(w);
                low[u]=min(low[u],low[w]);
            }
            else if(in_stk[w]) low[u]=min(low[u],dfn[w]);
        }
    
        if(dfn[u]==low[u]){
            ++scc_cnt;
            int y;
            do{
                y=stk[top--];
                in_stk[y]=false;
                id[y]=scc_cnt;
                sz[scc_cnt]++;
            }while(y!=u);
        }
    
    }
     
    int main(){
        ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
        cin>>n>>m>>s;
        rep(i,1,m){
            int u,v;
            cin>>u>>v;
            edge[u].pb(v);
        }
    
        rep(i,1,n){
            if(!dfn[i]) tarjan(i);
        }
     
        rep(i,1,n){
            for(auto w:edge[i]){
                int u=id[i];
                int v=id[w];
                if(u!=v){
                    din[v]++;
                }
            }
        }
    
        int ori=id[s];
        int ans=0;
        rep(i,1,scc_cnt){
            if(i==ori) continue;
            if(din[i]==0) ans++;
        }
    
        cout<<ans<<'\n';
     
        return 0;
    }
    
posted @ 2021-03-31 11:30  _Kolibri  阅读(51)  评论(0)    收藏  举报