POJ 3532 双连通缩点

来源:互联网 发布:大数据分析工作 编辑:程序博客网 时间:2024/06/06 07:11

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

 

*/

 

0 0