• cf999E (强联通分量模板题)


    给出n个点m条边的有向图,问至少添加多少条边使得任何点都可以从s点出发可达

    #include<bits/stdc++.h>
    #define forn(i, n) for (int i = 0 ; i < int(n) ; i++)
    #define fore(i, s, t) for (int i = s ; i < (int)t ; i++)
    #define fi first
    #define se second
    #define all(x) x.begin(),x.end()
    #define pf2(x,y) printf("%d %d
    ",x,y)
    #define pf(x) printf("%d
    ",x)
    #define each(x) for(auto it:x)  cout<<it<<endl;
    #define pi pair<int,int>
    using namespace std;
    typedef long long ll;
    const int maxn=1e6+5;
    const int maxm=2e5+5;
    const int inf=1e9;
    int head[maxn],ver[maxm],nex[maxm],tot;
    void inline AddEdge(int x,int y){
    	ver[++tot]=y,nex[tot]=head[x],head[x]=tot;
    }
    int dfn[maxn],low[maxn],num,sccnum,scc[maxn],s[maxn],d[maxn],top;
    void Tarjan(int x){
    	low[x]=dfn[x]=++num;
    	s[++top]=x;
    	for(int i=head[x];i;i=nex[i]){
    		int y=ver[i];
    		if(!dfn[y]) {
    			Tarjan(y);
    			low[x]=min(low[x],low[y]);
    		}
    		else if(!scc[y]) low[x]=min(low[x],dfn[y]);//说明找到了一条反祖边 
    	}
    	if(low[x]==dfn[x]) {
    		sccnum++;
    		while(s[top]!=x) {
    			scc[s[top]]=sccnum;
    			top--;
    		}
    		scc[s[top]]=sccnum;
    		top--;
    	}
    }
    int main(){
    	int n,m,s;
    	cin>>n>>m>>s;
    	for(int i=0;i<m;i++){
    		int x,y;
    		scanf("%d%d",&x,&y);
    		AddEdge(x,y);
    	}
    	for(int i=1;i<=n;i++)
    		if(!dfn[i]) Tarjan(i);
    	for(int x=1;x<=n;x++){
    		for(int i=head[x];i;i=nex[i]){
    			int y=ver[i];
    			if(scc[x]!=scc[y]){
    				d[scc[y]]++;
    			}
    		}
    	}
    	int ans=0;
    	for(int i=1;i<=sccnum;i++)
    		if(!d[i] && i!=scc[s]) ans++;
    	cout<<ans<<endl; 
    }
    

      

  • 相关阅读:
    hyper-v使用wifi链接网络
    windows下批量换程序——运维常用
    redis多端口,多实例。
    vs2017 本地IP地址调试 局域网调试
    自动备份
    ipv6无网络访问权限怎么办
    缓存
    学习php
    DateTimeOffset DateTime
    C# 集合
  • 原文地址:https://www.cnblogs.com/033000-/p/12345095.html
Copyright © 2020-2023  润新知