(边双联通+树直径) hdu 4612

Warm up

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

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

Author

SYSU

题意

一个无向图,现在要添加一条边,使得桥的数量最少并输出。

首先添加的边肯定是树的直径两个端点,所以我们只需要求出 总的桥-树直径就可以了啊

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<string>
#include<algorithm>
#include<queue>
#include<vector>
#include<set>
#include<stack>
using namespace std;
vector<int> e[200005],mp[200005];
int n,m,use[200005],top,newflag,Dfs[200005],low[200005],isstack[200005];
int dp[200005],vis[200005],ans,bridge;
stack<int> s;
void init()
{
    ans=0,bridge=0;
    memset(use,0,sizeof(use));
    memset(Dfs,0,sizeof(Dfs));
    memset(low,0,sizeof(low));
    memset(isstack,0,sizeof(isstack));
    top=newflag=0;
    while(!s.empty())
        s.pop();
    for(int i=1;i<=n;i++)
        e[i].clear(),mp[i].clear();
}
int bfs(int x)
{
    int pos;
    pos=x;
    memset(vis,0,sizeof(vis));
    memset(dp,0,sizeof(dp));
    queue<int> q;
    q.push(x);
    vis[x]=1;
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        for(int i=0;i<mp[u].size();i++)
        {
            int v=mp[u][i];
            if(vis[v]) continue;
            vis[v]=1;
            dp[v]=dp[u]+1;
            q.push(v);
            if(dp[v]>ans)
            {
                ans=dp[v];
                pos=v;
            }
        }
    }
    return pos;
}
void tarjan(int u,int father)
{
    Dfs[u]=low[u]=++top;
    s.push(u);
    isstack[u]=1;
    int cnt=0;
    for(int i=0;i<e[u].size();i++)
    {
        int v=e[u][i];
        if(!Dfs[v])
        {
            tarjan(v,u);
            low[u]=min(low[u],low[v]);
            if(low[v]>Dfs[u])
                bridge++;
        }
        else if(v==father)
        {
            if(cnt) low[u]=min(low[u],Dfs[v]);
            cnt++;
        }
        else if(isstack[v])
            low[u]=min(low[u],Dfs[v]);
    }
    if(low[u]==Dfs[u])
    {
        newflag++;
        int x;
        do
        {
            x=s.top();
            s.pop();
            isstack[x]=0;
            use[x]=newflag;
        }while(x!=u);
    }
}
int main()
{
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        if(n==0&&m==0)
            break;
        init();
        for(int i=1;i<=m;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            e[x].push_back(y);
            e[y].push_back(x);
        }
        for(int i=1;i<=n;i++)
        {
            if(!Dfs[i])
                tarjan(i,-1);
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=0;j<e[i].size();j++)
            {
                int u,v;
                u=i,v=e[i][j];
                if(use[u]!=use[v])
                    mp[use[u]].push_back(use[v]);
            }
        }
        bfs(bfs(1));
        printf("%d\n",bridge-ans);
    }
    return 0;
}

  

时间: 2025-01-01 01:12:34

(边双联通+树直径) hdu 4612的相关文章

HDU 4612 Warm up(边双联通求树的直径)

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

HDU 4612 双联通分量+树的直径

点击打开链接 题意:给一个无向联通图,里面可能有重边,问添加一条边后,使得图中的桥最小,将桥的数量输出 思路:刚刚读完题,就有了思路去写,无非就是将联通图双联通分量后缩点,然后求一条最长的路,首尾相连,肯定将更多的桥包含使得这些桥不再是桥,很好想的题,但是错了20+什么鬼,md重边这么难处理,醉了~~~,之前的做法是将重边全部找出来,希望数据弱点水过去算了,TLE好样的,那么我们在处理桥的时候,也就是找桥的时候,如果是桥,我们将这条边标记一下,然后找所有边时加上就行了,在一个就是找树的直径,两次

HDU 4612——Warm up——————【边双连通分量、树的直径】

Warm up Time Limit:5000MS     Memory Limit:65535KB     64bit IO Format:%I64d & %I64u Submit Status Practice HDU 4612 Description N planets are connected by M bidirectional channels that allow instant transportation. It's always possible to travel bet

hdu 4612 Warm up 双连通缩点+树的直径

首先双连通缩点建立新图(顺带求原图的总的桥数,其实由于原图是一个强连通图,所以桥就等于缩点后的边) 此时得到的图类似树结构,对于新图求一次直径,也就是最长链. 我们新建的边就一定是连接这条最长链的首尾,这样就将原图的桥减少了直径个. #include<iostream> #include<cstring> #include<cstdio> #include<vector> #include<algorithm> #include<map&g

hdu 4612 缩点 桥 树的直径

// http://acm.hdu.edu.cn/showproblem.php?pid=4612 // 大致题意: 给n个点和m条边,组成一个无向连通图,问  给我加一条边的权力(可连接任意两点)->让图的桥数量最小,输出此时桥的数量.(2<=N<=200000, 1<=M<=1000000) // 无向环里面的边没有桥,缩点,因为是连通图,所以缩完点后构成了一棵树,每条树边都是一个桥.要加一条边使得加完后图的桥数最小,结合上述,所以选择连接树直径的两端点.ans = 原先

Hdu 4612 Warm up (双连通分支+数的直径)

题目链接: Hdu 4612 Warm up 题目描述: 给一个无向连通图,问加上一条边后,桥的数目最少会有几个? 解题思路: 题目描述很清楚,题目也很裸,就是一眼看穿怎么做的,先求出来双连通分量,然后缩点重新建图,用bfs求树的直径,直径的长度就是减去桥的数目. 这个题目需要手动扩展,而且手动扩展的话要用C++提交,G++re哭了. 1 #include <cstdio> 2 #include <queue> 3 #include <cstring> 4 #inclu

[HDOJ4612]Warm up(双连通分量,缩点,树直径)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4612 所有图论题都要往树上考虑 题意:给一张图,仅允许添加一条边,问能干掉的最多条桥有多少. 必须解决重边的问题,最后会说. 首先tarjan跑出所有的双连通分量和是桥的边还有桥的数量,这非常重要.接着缩点重新建图,然后两遍dfs找出两个在树上距离最远的点.我的想法就是把这条最长的链连成一个环,让它成为一个双连通分量,这样的效果是最好的.最后就是用桥的数量减去树直径再减一就得到了剩下的桥的数量了.求

HDU 4738 --Caocao&#39;s Bridges 【无向图边双联通 &amp;&amp; 求权值最小的桥 &amp;&amp; 模板】

Caocao's Bridges Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2641    Accepted Submission(s): 855 Problem Description Caocao was defeated by Zhuge Liang and Zhou Yu in the battle of Chibi. B

HDU 4738 Caocao&#39;s Bridges(双联通分量+并查集)

大意:有n座岛和m条桥,每条桥上有w个兵守着,现在要派不少于守桥的士兵数的人去炸桥,只能炸一条桥,使得这n座岛不连通,求最少要派多少人去. 思路:我们就是要缩点后直接求桥上人的最少数量.(PS:1.注意图如果不联通直接输出0.2.如果图中的桥上人为0,个那么要让一个人去.3.重边的问题.这里可以忽略) #include<map> #include<queue> #include<cmath> #include<cstdio> #include<stac