标签:
| Time Limit: 5000MS | Memory Limit: 65536K | |
| Total Submissions: 4589 | Accepted: 1512 |
Description
Input
Output
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;
}版权声明:本文为博主原创文章,未经博主允许不得转载。
POJ 2117--Electricity【点双联通 && 求删去一个点后,图最多有多少块连通】
标签:
原文地址:http://blog.csdn.net/hpuhjh/article/details/47748665