POJ 2117--Electricity【点双联通 && 求删去一个点后,图最多有多少块连通】

Electricity

Time Limit: 5000MS   Memory Limit: 65536K
Total Submissions: 4589   Accepted: 1512

Description

Blackouts and Dark Nights (also known as ACM++) is a company that provides electricity. The company owns several power plants, each of them supplying a small area that surrounds it. This organization brings a lot of problems - it often happens that there is
not enough power in one area, while there is a large surplus in the rest of the country.

ACM++ has therefore decided to connect the networks of some of the plants together. At least in the first stage, there is no need to connect all plants to a single network, but on the other hand it may pay up to create redundant connections on critical places
- i.e. the network may contain cycles. Various plans for the connections were proposed, and the complicated phase of evaluation of them has begun.

One of the criteria that has to be taken into account is the reliability of the created network. To evaluate it, we assume that the worst event that can happen is a malfunction in one of the joining points at the power plants, which might cause the network
to split into several parts. While each of these parts could still work, each of them would have to cope with the problems, so it is essential to minimize the number of parts into which the network will split due to removal of one of the joining points.

Your task is to write a software that would help evaluating this risk. Your program is given a description of the network, and it should determine the maximum number of non-connected parts from that the network may consist after removal of one of the joining
points (not counting the removed joining point itself).

Input

The input consists of several instances.

The first line of each instance contains two integers 1 <= P <= 10 000 and C >= 0 separated by a single space. P is the number of power plants. The power plants have assigned integers between 0 and P - 1. C is the number of connections. The following C lines
of the instance describe the connections. Each of the lines contains two integers 0 <= p1, p2 < P separated by a single space, meaning that plants with numbers p1 and p2 are connected. Each connection is described exactly once and there is at most one connection
between every two plants.

The instances follow each other immediately, without any separator. The input is terminated by a line containing two zeros.

Output

The output consists of several lines. The i-th line of the output corresponds to the i-th input instance. Each line of the output consists of a single integer C. C is the maximum number of the connected parts of the network that can be obtained by removing
one of the joining points at power plants in the instance.

Sample Input

3 3
0 1
0 2
2 1
4 2
0 1
2 3
3 1
1 0
0 0

Sample Output

1
2
2

求删除一个点后, 图中最多有多少个连通块

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <stack>
#define maxn 100000+10
#define maxm 2000000+10
using namespace std;
int n ,m;
struct node {
    int u, v, next;
};

node edge[maxm];
int head[maxn], cnt;
int low[maxn];//从该点或它的子孙出发 通过回边可以到达的最低
int dfn[maxn];//该点的深度优先数
bool is_cut[maxn];//标记该点是不是割点
int add_bcc[maxn];//去掉该点增加的bcc数目
int dfs_clock;//深度优先数计数器
int bccno[maxn];//属于哪个bcc
int bcc_cnt;//bcc计数器
int num;
void init(){
    cnt = 0;
    memset(head, -1, sizeof(head));
}

void add(int u, int v){
    edge[cnt] = {u, v, head[u]};
    head[u] = cnt++;
    edge[cnt] = {v, u, head[v]};
    head[v] = cnt++;
}

void getmap(){
    while(m--){
        int a, b;
        scanf("%d%d", &a, &b);
        a++, b++;
        add(a, b);
    }
}
void tarjan(int u, int fa){
    low[u] = dfn[u] = ++dfs_clock;
    int son = 0;
    for(int i = head[u]; i != -1; i = edge[i].next){
        int v = edge[i].v;
        if(!dfn[v]){
            son++;
            tarjan(v, u);
            low[u] = min(low[u], low[v]);
            if( u != fa && low[v] >= dfn[u]){ // u 是割点,但不是根节点
                is_cut[u] = true;
                //记录 u 有几个满足low[v] >= dfn[u]的子节点 v,
                //若有d个,去掉该割点后分成了 d + 1个连通分量,新增了d个
                add_bcc[u]++;
                //记录bcc里面的点
            }
        }
        else if(v != fa && dfn[v] < dfn[u]){
            low[u] = min(low[u], dfn[v]);//回边更新
        }
    }
    //u 是根节点, 但它的子节点只有一个,不是割点
    if(u == fa && son == 1) is_cut[u] = 0;
    //u 是根节点, 而且它的子节点个数 >= 2,是割点。删去该点后
    //u 有几个子节点, 就分成了几个bcc,新增了son - 1
    if(u == fa && son > 1) add_bcc[u] = son - 1;
}

void find(){
    memset(low, 0, sizeof(low));
    memset(dfn, 0, sizeof(dfn));
    memset(add_bcc, 0, sizeof(add_bcc));
    memset(is_cut, 0, sizeof(is_cut));
    memset(bccno, 0, sizeof(bccno));
    dfs_clock = bcc_cnt = 0;
    num = 0;//记录原来的联通块
    for(int i = 1; i <= n; ++i)
        if(!dfn[i]){
            tarjan(i, i);
            num++;
        }
}

void solve(){
    num = 0;
    find();
    int ans = 0;
    //printf("***%d\n", num);
    for(int i = 1; i <= n; ++i){
    	//printf("---%d\n", add_bcc[i]);
        ans = max(ans, add_bcc[i]);
    }
    printf("%d\n", ans + num);
}

int main (){
    while(scanf("%d%d", &n, &m), n || m){
    	if(m == 0){
    		printf("%d\n", n - 1);
    		continue;
		}
        init();
        getmap();
        solve();
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-29 00:24:23

POJ 2117--Electricity【点双联通 && 求删去一个点后,图最多有多少块连通】的相关文章

poj 2117 Electricity 【无向图求割点】【求去掉一个点后 图中最多的BCC数目】

Electricity Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 4597   Accepted: 1515 Description Blackouts and Dark Nights (also known as ACM++) is a company that provides electricity. The company owns several power plants, each of them sup

poj 2117 Electricity【点双连通求删除点后最多的bcc数】

Electricity Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 4727   Accepted: 1561 Description Blackouts and Dark Nights (also known as ACM++) is a company that provides electricity. The company owns several power plants, each of them sup

poj 2117 Electricity(tarjan求割点删掉之后的连通块数)

题目链接:http://poj.org/problem?id=2117 题意:求删除一个点后,图中最多有多少个连通块. 题解:就是找一下割点,根节点的割点删掉后增加son-1(son为子树个数),非根节点删掉之后++ #include <iostream> #include <cstring> #include <cstdio> using namespace std; const int N = 1e4 + 10; const int M = 1e6 + 10; st

HDU 4738 --Caocao&#39;s Bridges 【无向图边双联通 &amp;&amp; 求权值最小的桥 &amp;&amp; 模板】

Caocao's Bridges Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2641    Accepted Submission(s): 855 Problem Description Caocao was defeated by Zhuge Liang and Zhou Yu in the battle of Chibi. B

POJ 2117 Electricity

Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 5573   Accepted: 1818 Description Blackouts and Dark Nights (also known as ACM++) is a company that provides electricity. The company owns several power plants, each of them supplying a sma

HDU 4612 Warm up(边双联通求树的直径)

Problem Description N planets are connected by M bidirectional channels that allow instant transportation. It's always possible to travel between any two planets through these channels. If we can isolate some planets from others by breaking only one

tarjan双联通求割点和桥模板

  求割点 int n,m,stamp,low[1005],dfn[1005],iscut[1005];//iscut记录的为割点 vector<int> vec[1005]; void tarjan(int index,int fa){ int child=0; low[index]=dfn[index]=++stamp; for(int i=0;i<vec[index].size();i++) { int tmp=vec[index][i]; if(!dfn[tmp]) { chil

poj 3177 Redundant Paths (双联通)

/******************************************************* 题目:Redundant Paths (poj 2177) 链接:http://poj.org/problem?id=3177 算法:双联通+缩点 思路:先找出所有双联通分量,把这些分量缩成一个点 再找出所有度为一的点,用这些点数加一除2就可以了 ********************************************************/ #include<cs

poj 1144 Network【双连通分量求割点总数】

Network Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 11042   Accepted: 5100 Description A Telephone Line Company (TLC) is establishing a new telephone cable network. They are connecting several places numbered by integers from 1 to N