您的位置:首页 > 其它

POJ 3532 双连通缩点

2015-08-24 15:41 288 查看
POJ 3352

题目链接:
http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=11219
题意:

一些点之间有边相连,保证整个图连通。问至少增加几条边,能使得去掉任意一条原始边后原图仍然保持连通。

思路:

双连通缩点版题。

最后答案为(缩点树种度为1的点个数+1)/2。因为是测版,所以看题解过的~

源码:

#include <cstdio>

#include <cstring>

#include <cmath>

#include <cstdlib>

#include <algorithm>

#include <iostream>

#include <utility>

#include <vector>

using namespace std;

#define gmax(a,b) ((a) > (b) ? (a) : (b))

#define gmin(a,b) ((a) < (b) ? (a) : (b))

const int MAXN = 1000 + 5;

typedef pair<int, int>pii;

vector<pii>lin[MAXN];

int n, m;

int bridge[MAXN];

int U[MAXN], V[MAXN];

int low[MAXN], pre[MAXN], clock;

int NewId[MAXN], IDs; ///新点标号,总的新点数

int vis[MAXN];

void edge_init()

{

for(int i = 1 ; i <= n ; i++)

lin[i].clear();

int u, v;

for(int i = 1 ; i <= m ; i++){

scanf("%d%d", &u, &v);

lin[u].push_back(make_pair(v, i));

lin[v].push_back(make_pair(u, i));

U[i] = u, V[i] = v;

}

}

void DFS_bridge(int u, int fa)

{

pre[u] = low[u] = ++clock;

for(int i = 0 ; i < (int)lin[u].size() ; i++){

pii temp = lin[u][i];

int v = temp.first, ID = temp.second;

if(pre[v] == 0){

DFS_bridge(v, u);

low[u] = gmin(low[u], low[v]);

if(low[v] > pre[u]) bridge[ID] = 1;

}

else if(pre[v] != 0 && v != fa)

low[u] = gmin(low[u], pre[v]);

}

}

void DFS_shrink(int u, int fa)

{

NewId[u] = IDs;

vis[u] = 1;

for(int i = 0 ; i < (int)lin[u].size() ; i++){

int v = lin[u][i].first;

int ID = lin[u][i].second;

if(!bridge[ID] && v != fa && vis[v] == 0){

DFS_shrink(v, u);

}

}

}

void BCC_bridge()

{

memset(bridge, 0, sizeof(bridge));

memset(pre, 0, sizeof(pre));

clock = 0;

for(int i = 1 ; i <= n ; i++)

if(pre[i] == 0)

DFS_bridge(1, -1);

}

void Shrink() ///关键函数

{

memset(vis, 0, sizeof(vis));

IDs = 0;

for(int i = 1 ; i <= n ; i++){

if(vis[i] == 0){

++IDs;

DFS_shrink(i, -1);

}

}

for(int i = 1 ; i <= n ; i++)

lin[i].clear();

for(int i = 1 ; i <= m ; i++){ ///新点的边

if(bridge[i]){

int u = NewId[U[i]], v = NewId[V[i]];

lin[u].push_back(make_pair(v, i));

lin[v].push_back(make_pair(u, i));

}

}

}

int main()

{

while(scanf("%d%d", &n, &m) != EOF){

edge_init();

BCC_bridge();

Shrink();

int ans = 0;

for(int i = 1; i <= IDs ; i++){

if(lin[i].size() == 1){

// printf("i = %d\n", i);

ans++;

}

}

ans = (ans + 1) / 2;

printf("%d\n", ans);

}

return 0;

}

/*

7 6

1 2

2 3

3 4

4 5

5 6

1 7



*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: