hdu 3844 la 5135 点双连通分量

Mining Your Own Business

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 769    Accepted Submission(s): 97


Problem Description
John Digger is the owner of a large illudium phosdex mine. The mine is made up of a series of tunnels that meet at various large junctions. Unlike some owners, Digger actually cares about the welfare of his workers and has a concern about the layout of the mine. Specifically, he worries that there may a junction which, in case of collapse, will cut off workers in one section of the mine from other workers (illudium phosdex, as you know, is highly unstable). To counter this, he wants to install special escape shafts from the junctions to the surface. He could install one escape shaft at each junction, but Digger doesn’t care about his workers that much. Instead, he wants to install the minimum number of escape shafts so that if any of the junctions collapses, all the workers who survive the junction collapse will have a path to the surface.

Write a program to calculate the minimum number of escape shafts and the total number of ways in which this minimum number of escape shafts can be installed.
 

 

Input
The input consists of several test cases. The first line of each case contains a positive integer N (N <= 5×10^4) indicating the number of mine tunnels. Following this are N lines each containing two distinct integers s and t, where s and t are junction numbers. Junctions are numbered consecutively starting at 1. Each pair of junctions is joined by at most a single tunnel. Each set of mine tunnels forms one connected unit (that is, you can get from any one junction to any other).

The last test case is followed by a line containing a single zero.
 

 

Output
For each test case, display its case number followed by the minimum number of escape shafts needed for the system of mine tunnels and the total number of ways these escape shafts can be installed. You may assume that the result fits in a signed 64-bit integer.

Follow the format of the sample output.
 

 

Sample Input
9 1 3 4 1 3 5 1 2 2 6 1 5 6 3 1 6 3 2 6 1 2 1 3 2 4 2 5 3 6 3 7 0
 

 

Sample Output
Case 1: 2 4 Case 2: 4 1
 

 

Source
 
referenced from LRJ...
firstly we should figure out Biconnected Component, and then for some component if it has
1.0 cut: this means the given graph is BCC, so we can arbitarily select 2 nodes;
2.1 cut:when this BCC has only one cut, we should select any one node but that cut to build security facilities such that, any node of this component collapses,workers in this component can survive;
3.more cuts:because one BCC can share more cuts with other BCCs, so worker from any one of this component can run to adjacent BCCs to escape,  thus in this case, we can simply not build security facilities.
(因为一个双连通分量可以与多个双连通分量相连,形成多个割点,此时该分量任一点collapse,分量内点都可到达相连分量点,从而逃生。)
另外,竟然用到了传说的扩栈(预处理指令?): #pragma comment(linker,"/STACK:102400000,102400000")  而且要用c++编译器交。。。
msdn有关于该预处理指令(?)的解释。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<vector>
#include<cstdlib>
#include<algorithm>
#include<stack>

using namespace std;

#define LL __int64
#define ULL unsigned long long
#define UINT unsigned int
#define MAX_INT 0x7fffffff
#define MAX_LL 0x7fffffffffffffff
#define MAX(X,Y) ((X) > (Y) ? (X) : (Y))
#define MIN(X,Y) ((X) < (Y) ? (X) : (Y))

#define MAXN 200100

#pragma comment(linker,"/STACK:102400000,102400000")

struct edge{
    int u, v;
};

int dfn[MAXN], low[MAXN], cnt, tsp;
int id[MAXN], iscut[MAXN];
vector<int> bcc[MAXN];


vector<int> g[MAXN];
stack<edge> s;

void tarjan(int u, int fa){
    int v, child=0;
    dfn[u]=low[u]=++tsp;
    for(unsigned int i=0; i<g[u].size(); i++){
        v=g[u][i];
        edge t;     t.u=u;      t.v=v;
        if(!dfn[v]){
            child++;
            s.push(t);
            tarjan(v, u);
            low[u]=MIN(low[u], low[v]);
            if(low[v]>=dfn[u]){
                iscut[u]=1;
                edge k;
                bcc[++cnt].clear();
                while(1){
                    k=s.top();      s.pop();
                    if(id[k.u] != cnt) {id[k.u]=cnt; bcc[cnt].push_back(k.u);}
                    if(id[k.v] != cnt) {id[k.v]=cnt; bcc[cnt].push_back(k.v);}
                    if(k.u==u && k.v==v) break;
                }
            }
        }
        else if(dfn[v]<dfn[u] && v!=fa) s.push(t), low[u]=MIN(low[u], dfn[v]);
    }
    if(fa<0 && child==1) iscut[u]=0;
}

void solve(int n){
    tsp=cnt=0;
    memset(dfn, 0, sizeof(dfn));
    memset(id, 0, sizeof(id));
    memset(iscut, 0, sizeof(iscut));
    tarjan(0, -1);
    int ans1=0;           LL ans2=1;
    for(int i=1; i<=cnt; i++){
        int num=0;
        for(int j=0; j<bcc[i].size(); j++){
            if(iscut[bcc[i][j]]) num++;
        }
        if(num==1) ans1++, ans2*=(bcc[i].size()-1); //..............................
    }
    if(cnt==1) ans1=2, ans2=(LL)n*(n-1)/2;              //..............................
    printf("%d %I64d\n", ans1, ans2);
}

int main(){
    freopen("C:\\Users\\Administrator\\Desktop\\in.txt","r",stdin);
    int n, kase=1;
    while(scanf(" %d", &n)==1 && n){
        int i, m=n, u, v;
        n=-1;
        for(i=0; i<MAXN; i++) g[i].clear();
        for(i=0; i<m; i++){
            scanf(" %d %d", &u, &v);    u--;        v--;
            g[u].push_back(v);      g[v].push_back(u);
            n=MAX(n,1+v);
            n=MAX(n, 1+u);
        }
        printf("Case %d: ", kase++);
        solve(n);
    }
    return 0;
}

 

 
posted @ 2013-09-06 17:48  Ramanujan  阅读(282)  评论(0编辑  收藏  举报