zoukankan      html  css  js  c++  java
  • 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; 
    }
    

      

  • 相关阅读:
    C语言II博客作业04
    C语言II博客作业03
    C语言II博客作业02
    C语言II博客作业01
    学期总结
    C语言I博客作业08
    C语言I博客作业07
    C语言I博客作业06
    C语言I博客作业05
    C语言I博客作业04
  • 原文地址:https://www.cnblogs.com/033000-/p/12345095.html
Copyright © 2011-2022 走看看