hdu 4612 Warm up (手动扩栈,求树上哪两个点的距离最远)

http://acm.hdu.edu.cn/showproblem.php?pid=4612

Warm up

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)
Total Submission(s): 4743    Accepted Submission(s): 1063


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 channel , the channel is called a bridge of the transportation system.
People don't like to be isolated. So they ask what's the minimal number of bridges they can have if they decide to build a new channel.
  Note that there could be more than one channel between two planets.
 

Input
  The input contains multiple cases.
  Each case starts with two positive integers N and M , indicating the number of planets and the number of channels.
  (2<=N<=200000, 1<=M<=1000000)
  Next M lines each contains two positive integers A and B, indicating a channel between planet A and B in the system. Planets are numbered by 1..N.
  A line with two integers '0' terminates the input.
 

Output
  For each case, output the minimal number of bridges after building a new channel in a line.
 

Sample Input
   
   
   
   
4 4 1 2 1 3 1 4 2 3 0 0
 

Sample Output
   
   
   
   
0
 

题目大意:
给你一个无向图,问加一条边之后最少还剩下几座桥。
(注意重边处理)

分析:其实当我们把边双连通分量给求出来之后我们就能将连通块求出来,这样我们就可以重新构图。重新构造出来的图肯定是一颗树了,
那么问题就转化为求树的哪两个节点的距离最长。我们可以随便找一个点S开始BFS, BFS到这个点最远的那个点P,然后再从这个最远点P开始BFS,BFS到P最远的点E,  PE之间的距离就是这个图上最大的距离。

注:此题需要手动扩栈
#pragma comment (linker, "/STACK:102400000,102400000")///手动扩栈

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <limits>
#include <queue>
#include <stack>
#include <vector>
#include <map>

using namespace std;

#define N 200005
#define INF 0xfffffff
#define PI acos (-1.0)
#define EPS 1e-8

vector <vector <int> > G1;
vector <vector <int> > G2;

int n, m, Time, cnt, top;
int low[N], dfn[N], Stack[N], ft[N], f[N], step[N];

void Init ();
void tarjan (int u, int fa);
int BFS (int s, int flag);
void solve ();

int main ()
{
    while (scanf ("%d%d", &n, &m), n+m)
    {
        Init ();
        while (m--)
        {
            int a, b;
            scanf ("%d%d", &a, &b);
            G1[a].push_back (b);
            G1[b].push_back (a);
        }
        solve ();
    }
    return 0;
}

void Init ()
{
    G1.clear ();
    G1.resize (n+2);
    G2.clear ();
    G2.resize (n+2);
    memset (low, 0, sizeof (low));
    memset (dfn, 0, sizeof (dfn));
    memset (f, 0, sizeof (f));
    memset (ft, 0, sizeof (ft));
    memset (Stack, 0, sizeof (Stack));
    Time = cnt = top = 0;
}

void tarjan (int u, int fa)
{
    low[u] = dfn[u] = ++Time;
    Stack[top++] = u;
    f[u] = fa;
    int len = G1[u].size (), v, k = 0;

    for (int i=0; i<len; i++)
    {
        v = G1[u][i];
        if (!k && v == fa)
        {
            k++;
            continue;
        }
        if (!low[v])
        {
            tarjan (v, u);
            low[u] = min (low[u], low[v]);
        }
        else
            low[u] = min (low[u], dfn[v]);
    }

    if (low[u] == dfn[u])
    {
        do
        {
            v = Stack[--top];
            ft[v] = cnt;
        }while (u != v);
        cnt++;
    }
}

int BFS (int s, int flag)
{
    int p, pn;
    queue <int> que;
    que.push (s);
    memset (step, -1, sizeof (step));
    step[s] = 0;

    while (que.size ())
    {
        p = que.front (); que.pop ();
        int len = G2[p].size ();
        for (int i=0; i<len; i++)
        {
            pn = G2[p][i];
            if (step[pn] == -1)
            {
                step[pn] = step[p] + 1;
                que.push (pn);
            }
        }
    }
    if (flag == 1) return p;
    return step[p];
}

void solve ()
{
    int ans = 0;
    for (int i=1; i<=n; i++)
        if (!low[i]) tarjan (i, i);

    for (int i=1; i<=n; i++)
    {
        int v = f[i];
        if (ft[i] != ft[v])
        {///重新构图
            G2[ft[i]].push_back (ft[v]);
            G2[ft[v]].push_back (ft[i]);
        }
    }
    int p = BFS (0, 1);///以0为起点经行一次BFS返回最远距离的编号
    ans = cnt - BFS (p, 2) - 1;///返回最远距离的长度
    printf ("%d\n", ans);
}



你可能感兴趣的:(hdu 4612 Warm up (手动扩栈,求树上哪两个点的距离最远))