码迷,mamicode.com
首页 > 其他好文 > 详细

cf1276B——割点+深搜树

时间:2019-12-28 19:12:59      阅读:67      评论:0      收藏:0      [点我收藏+]

标签:efi   back   can   div   --   cin   scan   统计   its   

/*
如果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)<<\n;
        
    }    
    return 0;
}

cf1276B——割点+深搜树

标签:efi   back   can   div   --   cin   scan   统计   its   

原文地址:https://www.cnblogs.com/zsben991126/p/12112477.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!