hdu 4612 Warm up (帶有重邊的無向圖Tarjan+樹的直徑)

Warm up

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


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
 


題意:有N個點,M條邊,加一條邊,求割邊最少(有重邊,所有點在原圖中都是連通的)。

割邊:在原圖中去掉該邊,原圖變得不連通,這樣的邊成爲割邊。

思路:先求無向圖的連通分量,縮點形成一個生成樹,可知樹中所有邊都爲割邊,採用貪

心的策略可知,再加一條邊,最少的割邊數爲 ans = 所有割邊數 - 數的直徑 。

 
因爲有的圖上可能有重邊,這樣不好處理。我們記錄每條邊的標號(一條無向邊拆成的兩

條有向邊標號相同)這樣就能限制不走一樣的邊而能走重邊!



#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <vector>
#include <stack>
using namespace std;
const int maxn=200010;

struct edge
{
    int u,v;
    edge() {}
    edge(int uu,int vv):u(uu),v(vv) {}
} a[maxn*10];

int n,m,dfs_clock,cnt,index,id[maxn],S[maxn],low[maxn],dfn[maxn],belong[maxn],num[maxn];
vector <int> G[maxn],T[maxn];
stack <int> st;
bool mark[maxn],visited[maxn*10];

void initial()
{
    memset(low,0,sizeof(low));
    memset(dfn,0,sizeof(dfn));
    memset(num,0,sizeof(num));
    memset(mark,0,sizeof(mark));
    memset(belong,0,sizeof(belong));
    memset(visited,0,sizeof(visited));
    for(int i=0; i<maxn; i++)
    {
        T[i].clear();
        G[i].clear();
    }
    while(!st.empty())  st.pop();
    index=0;
    dfs_clock=1;
    cnt=0;
}

void input()
{
    int u,v;
    for(int i=0; i<m; i++)
    {
        scanf("%d %d",&u,&v);
        G[u].push_back(cnt);
        a[cnt++]=edge(u,v);
        G[v].push_back(cnt);
        a[cnt++]=edge(v,u);
    }
}

void tarjan(int u,int fa)
{
    dfn[u]=low[u]=dfs_clock++;
    st.push(u);
    mark[u]=1;
    for(int i=0; i<G[u].size(); i++)
    {
        int tp=G[u][i];
        if(visited[tp])  continue;
        visited[tp]=visited[tp^1]=1;
        int v=a[tp].v;
        if(!dfn[v])
        {
            tarjan(v,tp);
            low[u]=min(low[v],low[u]);
        }
        else if(mark[v])  low[u]=min(low[u],dfn[v]);
    }
    if(low[u]==dfn[u])
    {
        index++;
        while(1)
        {
            int t=st.top();
            st.pop();
            belong[t]=index;
            if(t==u)  break;
        }
    }
}

void solve1()
{
    for(int i=1; i<=n; i++)
        if(!dfn[i])
            tarjan(i,-1);
    for(int i=0; i<cnt; i+=2)
    {
        int p=belong[a[i].u],q=belong[a[i].v];
        if(p!=q)
        {
            T[p].push_back(q);
            T[q].push_back(p);
        }
    }
}

void dfs(int u,int v,int depth)
{
    num[v]=depth;
    for(int i=0; i<T[v].size(); i++)
    {
        int vv=T[v][i];
        if(vv==u)  continue;
        dfs(v,vv,depth+1);
    }
}

void solve2()
{
    int Max=-1,k=-1;
    dfs(-1,1,0);
    for(int i=1; i<=index; i++)  if(Max<num[i])  Max=num[i],k=i;
    memset(num,0,sizeof(num));
    dfs(-1,k,0);
    for(int i=1; i<=index; i++)  Max=max(Max,num[i]);
    printf("%d\n",index-1-Max);
}

int main()
{
    while(scanf("%d %d",&n,&m)!=EOF)
    {
        if(n==0 && m==0)  break;
        initial();
        input();
        solve1();
        solve2();
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章