• cf1276B——割点+深搜树


    /*
    如果ab都是图的割点,那么答案非0,反之答案是0
     把割点处断开后,原图裂成三张不联通的图,大小分别是size1,size2,size3.
     求出同时包含这两个割点的图,设大小是size1,那么答案就是(size2-1)*(size3-1) 
    */
    #include<bits/stdc++.h>
    #include<vector>
    using namespace std;
    #define ll long long 
    #define N 500005
    
    vector<int>G[N];
    int n,m,a,b;
    
    int low[N],dfn[N],index,cut[N];
    void tarjan(int u,int pre){
        low[u]=dfn[u]=++index;
        int son=0;//统计深搜树上儿子数量 
        for(auto v:G[u]){
            if(v==pre)continue;
            if(!dfn[v]){
                ++son;
                tarjan(v,u);
                low[u]=min(low[u],low[v]);
                if(u!=pre && dfn[u]<=low[v])//非树根割点 
                    cut[u]=true;
            }
            else low[u]=min(low[u],dfn[v]);
        }
        if(u==pre && son>1)cut[u]=1;//树根割点 
    }
    
    int vis[N],flag;
    int dfs1(int u){
        if(u==a || u==b)flag=1;
        int size=1;vis[u]=1;
        for(auto v:G[u]){
            if(vis[v])continue;
            size+=dfs1(v);
        }
        return size;
    }
    int dfs2(int u){
        if(u==a || u==b)flag=1;
        int size=1;vis[u]=1;
        for(auto v:G[u]){
            if(vis[v])continue;
            size+=dfs2(v);
        }
        return size;
    }
    
    int main(){
        int t;cin>>t;
        while(t--){
            scanf("%d%d%d%d",&n,&m,&a,&b);
            
            for(int i=1;i<=n;i++)G[i].clear();
            for(int i=1;i<=n;i++)low[i]=dfn[i]=cut[i]=vis[i]=0;
            index=0;
            
            for(int i=1;i<=m;i++){
                int u,v;scanf("%d%d",&u,&v);
                G[u].push_back(v);
                G[v].push_back(u);
            }
            tarjan(1,1); 
            
            if(!cut[a] || !cut[b]){puts("0");continue;} 
            
            //ab将图分成三块,分别求出这三块的size
            ll sizea=1;vis[a]=1;
            for(auto v:G[a]){
                if(vis[v])continue;
                flag=0;
                int res=dfs1(v);
                if(!flag)sizea+=res;
            } 
            
            for(int i=1;i<=n;i++)vis[i]=0;
            ll sizeb=1;vis[b]=1;
            for(auto v:G[b]){
                if(vis[v])continue;
                flag=0;
                int res=dfs2(v);
                if(!flag)sizeb+=res;
            }
            
            cout<<(sizea-1)*(sizeb-1)<<'
    ';
            
        }    
        return 0;
    }
  • 相关阅读:
    [array] leetcode
    [array] leetCode-27. Remove Element
    [array] leetCode-26. Remove Duplicates from Sorted Array
    [array] leetCode-18. 4Sum -Medium
    [array] leetCode-15. 3Sum-Medium
    [array] leetCode-16. 3Sum Closest -Medium
    [array] leetCode-11. Container With Most Water-Medium
    [array] leetCode-4-Median of Two Sorted Arrays-Hard
    [array] leetCode-1-Two Sum-Easy
    【读书笔记与思考】Andrew 机器学习课程笔记
  • 原文地址:https://www.cnblogs.com/zsben991126/p/12112477.html
Copyright © 2020-2023  润新知