LA 5135 Mining Your Own Business (求割点与BCC)

来源:互联网 发布:牛知天骄潮汕鲜牛肉 编辑:程序博客网 时间:2024/06/11 18:31

题目大意:n个点,m条边,选择尽量少的点作为太平井,使得删除任意一个点,其余顶点都有到太平井的路径。问需要安装的最少的太平井数目,以及对应的方案数。

模型:无向图中选择尽量少的点涂黑(太平井),使得删除任意一个点后,每个连通分量至少有一个黑点。

分析后发现当点-双连通分量中割点的数目为1时,选择其余任意一个非割点的顶点涂黑即可;当整个图没有割点时,任意选两个点涂黑即可。


#include<bits/stdc++.h>using namespace std;typedef long long LL;#define maxn 50005struct Edge{    int u,v;};int dfn[maxn],iscut[maxn],bccno[maxn],dfs_clock,bcc_cnt;vector<int> G[maxn],bcc[maxn];stack<Edge> S;int dfs(int u,int fa) //u在dfs树中的父节点为fa。{    int lowu=dfn[u]=++dfs_clock,child=0;    for(int i=0; i<G[u].size(); ++i)    {        int v=G[u][i];        Edge e=(Edge)        {            u,v        };        if(!dfn[v]) //没有访问过v        {            S.push(e);            ++child;            int lowv=dfs(v,u);            lowu=min(lowu,lowv);//用后代的low函数更新自己            if(lowv>=dfn[u])            {                iscut[u]=1;                bcc_cnt++;                bcc[bcc_cnt].clear();//bcc从1开始编号!!!!!                for(;;)                {                    Edge x=S.top();                    S.pop();                    if(bccno[x.u]!=bcc_cnt)                    {                        bcc[bcc_cnt].push_back(x.u);                        bccno[x.u]=bcc_cnt;                    }                    if(bccno[x.v]!=bcc_cnt)                    {                        bcc[bcc_cnt].push_back(x.v);                        bccno[x.v]=bcc_cnt;                    }                    if(x.u==u&&x.v==v) break;                }            }        }        else if(dfn[v]<dfn[u]&&v!=fa)   //用反向边更新自身            {                S.push(e);                lowu=min(lowu,dfn[v]);            }    }    if(fa<0&&child==1) iscut[u]=0;  //不要忘记这句啊!!!!!    return lowu;}void find_bcc(int n){    memset(dfn,0,sizeof(dfn));    memset(iscut,0,sizeof(iscut));    memset(bccno,0,sizeof(bccno));    dfs_clock=bcc_cnt=0;    for(int i=0;i<n;++i) if(!dfn[i]) dfs(i,-1);}int main(){    int ca=1,i,m,n=0,x,y,j;    while(~scanf("%d",&m)&&m){        for(i=0;i<maxn;++i) G[i].clear();        while(m--){            scanf("%d%d",&x,&y);            --x,--y;            G[x].push_back(y);            G[y].push_back(x);            n=max(n,max(x,y));        }        find_bcc(n);        LL ans1=0,ans2=1;        for(i=1;i<=bcc_cnt;++i){            int cut_cnt=0;            for(j=0;j<bcc[i].size();++j)                if(iscut[bcc[i][j]]) ++cut_cnt;            if(cut_cnt==1) {                ++ans1;                ans2*=(LL)(bcc[i].size()-cut_cnt);            }        }        if(bcc_cnt==1) {ans1=2;ans2=(LL)bcc[1].size()*(bcc[1].size()-1)/2;}        printf("Case %d: %lld %lld\n",ca++,ans1,ans2);    }    return 0;}


0 0
原创粉丝点击