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

UVALive 5135 Mining Your Own Business 双连通分量

时间:2015-09-08 12:17:36      阅读:139      评论:0      收藏:0      [点我收藏+]

标签:

据说这是一道Word Final的题,Orz。。。

原题链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3136

题意:

给你一个联通图,让你选择一些点,使得这个图的任意一个点消失后,其余的点都能到达某个你选择的点。问你最少选择哪些点,并且输出在最优的情况下,有多少方案。

题解:

一眼看过去,做法很简单,就删掉所有的割点后,考察联通块的个数就好。但这道题满满的坑。。要不怎么是总决赛的题。。

首先如果这个图只有一个联通块,那么答案就应该是任选两个点,这是因为,如果其中一个点挂了,还能走另外一个点。

如果一个联通块有大于一个割点,那么这个联通块就不需要,这是因为两个割点不可能同时挂了。

代码:

#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
#include<set>
#define MAX_V 50004
using namespace std;

int V=0;
vector<int> G[MAX_V];
int N;

int dfn[MAX_V],low[MAX_V],ind=0;
bool vis[MAX_V];
bool isCut[MAX_V];
int tot=0;

long long ways=1;
long long tmp=0;
long long cnt=0;

bool used[MAX_V];
set<int> se;

void init(){
    se.clear();
    V=ind=cnt=tmp=0;
    ways=1;
    memset(used,0,sizeof(used));
    memset(dfn,0,sizeof(dfn));
    memset(low,0,sizeof(low));
    memset(vis,0,sizeof(vis));
    memset(isCut,0,sizeof(isCut));
    for(int i=0;i<=N+2;i++)G[i].clear();
}

void Tarjan(int u,int p) {
    dfn[u] = low[u] = ++ind;
    vis[u]=1;
    int child = 0;
    for (int i = 0; i < G[u].size(); i++) {
        int v = G[u][i];
        if (v == p)continue;
        if (!vis[v]) {
            child++;
            Tarjan(v, u);
            low[u] = min(low[v], low[u]);
            if (p == 0 && child > 1)isCut[u] = 1;
            if (p&&low[v] >= dfn[u])
                isCut[u] = 1;
            tot+=isCut[u];
        }
        else
            low[u] = min(dfn[v], low[u]);
    }
}

void dfs(int u) {
    if (used[u] || isCut[u])return;
    tmp++;
    used[u] = 1;
    for (int i = 0; i < G[u].size(); i++){
        int v=G[u][i];
        if(isCut[v]){
            se.insert(v);
            continue;
        }
        dfs(v);
    }
}

int main() {
    int cas = 0;
    cin.sync_with_stdio(false);
    while (cin >> N) {
        tot=0;
        if (N == 0)break;
        init();
        for (int i = 0; i < N; i++) {
            int u, v;
            cin >> u >> v;
            V = max(V, max(u, v));
            G[u].push_back(v);
            G[v].push_back(u);
        }
        Tarjan(1, 0);
        cout << "Case " << ++cas << ": ";
        if (tot == 0) {
            cout << 2 << " " << (long long)V * (V - 1) / 2 << endl;
            continue;
        }
        for (int u = 1; u <= V; u++) {
            if (isCut[u])continue;
            tmp = 0;
            if (!used[u]) {
                se.clear();
                dfs(u);
                if (se.size() == 1 && tmp) {
                    ways *= tmp;
                    cnt++;
                }
            }
        }
        cout << cnt << " " << ways << endl;
    }
    return 0;
}

 

 

UVALive 5135 Mining Your Own Business 双连通分量

标签:

原文地址:http://www.cnblogs.com/HarryGuo2012/p/4791057.html

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