UvaLive5135 Mining Your Own Business(点双联通分量)

UvaLive5135 Mining Your Own Business

题意:有n条隧道,它们把一些矿点连接起来了。现在要在矿点处修建安全通道。使得当矿难在矿点处发生时。其他所有矿点的工人都能找到安全通道逃出去。输出需要的安全通道数以及方案数。

思路:建安全通道的话,肯定不能建在割顶,因为割顶如果崩塌了,割顶所连接的双连通分量内的点就跑不掉了,还得在双连通分量里面再建点(上述为双连通分量内部只有一个割顶的情况),这样不划算,还不如直接在里面建点 
如果一个双连通分量的内部割顶有多个的话,那么在这个双连通分量里面就可以不用建安全通道了,因为一个割顶崩塌了,还有其他点可以连向外面,所以,只考虑内部只有一个割顶的双连通分量要怎么建安全通道 
怎么建呢,排除掉割顶的所有的点都可以建

/*
ID: onlyazh1
LANG: C++
TASK: Guess
*/

#include<iostream>
#include<cmath>
#include<stack>
#include<queue>
#include<cctype>
#include<vector>
#include<cstring>
#include<fstream>
#include<iomanip>
#include<algorithm>
using namespace std;
typedef unsigned long long ll;

const int MAXN=50005<<1;
const int MAXM=1000010;
int n,m,u,v,tot;
int deg[MAXN];
int low[MAXN];
int dfn[MAXN];
bool cut[MAXN];
int head[MAXN];
int Stack[MAXN];
bool instack[MAXN];
vector<int> belong[MAXN];

int idx,top,block;
struct Edge{
    int v,nex;
}edge[MAXM<<1];

void addedge(int u,int v){
    edge[tot].v=v;
    edge[tot].nex=head[u];
    head[u]=tot++;
}

void Tarjan(int u,int pre){
    int son=0;
    low[u]=dfn[u]=++idx;
    Stack[top++]=u;
    instack[u]=true;
    for(int i=head[u];i!=-1;i=edge[i].nex){
        v=edge[i].v;
        if(v==pre) continue;
        if(!dfn[v]){
            Tarjan(v,u);
            low[u]=min(low[u],low[v]);
            if(u==pre) son++;
            if(low[v]>=dfn[u]){
                int vn;block++;
                belong[block].clear();
                do{
                    vn=Stack[--top];
                    belong[block].push_back(vn);
                    instack[vn]=false;
                }while(vn!=v);
                belong[block].push_back(u);
                if(u!=pre) cut[u]=true;
            }
        }
        else if(instack[v])
            low[u]=min(low[u],dfn[v]);
    }
    if(u==pre&&son>=2) cut[u]=true;
}

void init(){
    tot=top=idx=block=0;
    memset(deg,0,sizeof(deg));
    memset(dfn,0,sizeof(dfn));
    memset(low,0,sizeof(low));
    memset(head,-1,sizeof(head));
    memset(cut,false,sizeof(cut));
    memset(instack,false,sizeof(instack));
}
int main(){
    ifstream cin("in.txt");
    int n,icase=0;
    while(cin>>n&&n){
        init();
        int u,v,maxn=0;
        while(n--){
            cin>>u>>v;
            addedge(u,v);
            addedge(v,u);
            maxn=max(maxn,max(u,v));
        }
        for(int i=1;i<=maxn;i++)
            if(!dfn[i]) Tarjan(i,i);
        if(block==1){
            cout<<"Case "<<++icase<<": "<<2<<" "<<ll(maxn)*(maxn-1)/2<<endl;
            continue;
        }
        /*
        for(int i=1;i<=block;i++){
            cout<<belong[i].size()<<endl;
            for(int j=0;j<belong[i].size();j++)
                cout<<belong[i][j]<<" ";
            cout<<endl;
        }
        */
        ll ans1=0,ans2=1;
        for(int i=1;i<=block;i++){
            int cut_cnt=0;
            for(int j=0,sz=belong[i].size();j<sz;j++)
                if(cut[belong[i][j]]) cut_cnt++;
            if(cut_cnt==1){
                ans1++;ans2*=(belong[i].size()-1);
            }
        }
        cout<<"Case "<<++icase<<": "<<ans1<<" "<<ans2<<endl;
    }
    return 0;
}
View Code

 

posted on 2016-02-24 15:43  onlyAzha  阅读(286)  评论(1编辑  收藏  举报

导航