HDU4612:Warm up(缩点+树的直径)

Warm up

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

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4612

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

题意:

给出一个无向图,之后会加进来一条边,问加进来一条边过后,桥的最少数量为多少。

题解:

还是利用并查集先缩点,将无向图变为一颗树,树上每一条边都为桥。

然后加边我们希望尽量形成最大的环,那么考虑树的直径两端的点就满足了。

代码如下:

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <queue>
using namespace std;
typedef long long ll;
const int N = 2e5+5,M = 1e6+5;
int n,m;
int head[N];
struct Edge{
    int u,v,next;
    bool operator < (const Edge &A){
        if(u==A.u) return v<A.v;
        return u<A.u;
    }
}e[M<<1],g[M<<1];
int T,tot,cnt;
int dfn[N],low[N],cut[N],num[N],f[N];
void adde(int u,int v){
    e[tot].u=u;e[tot].v=v;e[tot].next=head[u];head[u]=tot++;
}
void init(){
    T=0;tot=0;cnt=0;
    memset(head,-1,sizeof(head));
    memset(cut,0,sizeof(cut));
    memset(dfn,0,sizeof(dfn));
    memset(num,0,sizeof(num));
    for(int i=0;i<=n+1;i++) f[i]=i;
}
int find(int x){
    return f[x]==x?f[x]:f[x]=find(f[x]);
}
void Union(int x,int y){
    int fx=find(x),fy=find(y);
    if(fx!=fy) f[fx]=fy;
}
void Tarjan(int u,int pre){
    dfn[u]=low[u]=++T;
    int k=0;
    for(int i=head[u];i!=-1;i=e[i].next){
        int v=e[i].v;
        if(v==pre && !k){
            k=1;
            continue ;
        }
        if(!dfn[v]){
            Tarjan(v,u);
            low[u]=min(low[u],low[v]);
        }else{
            low[u]=min(low[u],dfn[v]);
        }
        if(low[v]>dfn[u]){
            cut[v]=1;
        }else Union(u,v);
    }
}
int mx=0,node=1;
void dfs(int u,int d,int pa){
    if(d>mx){
        mx=d;
        node=u;
    }
    for(int i=head[u];i!=-1;i=e[i].next){
        int v=e[i].v;
        if(v==pa) continue ;
        dfs(v,d+1,u);
    }
}
int main(){
    while(scanf("%d%d",&n,&m)!=EOF){
        if(!n&&!m) break ;
        init();
        for(int i=1;i<=m;i++){
            int u,v;
            scanf("%d%d",&u,&v);
            adde(u,v);adde(v,u);
            if(u>v)swap(u,v);
            g[i].u=u;g[i].v=v;
        }
        sort(g+1,g+m+1);
        Tarjan(1,0);
        memset(head,-1,sizeof(head));tot=0;
        for(int i=1;i<=m;i++){
            int u=g[i].u,v=g[i].v;
            if(g[i].u==g[i-1].u&&g[i].v==g[i-1].v) continue ;
            int fx=find(u),fy=find(v);
            if(!num[fx]) num[fx]=++cnt;
            if(!num[fy]) num[fy]=++cnt;
            if(num[fx]==num[fy]) continue ;
            adde(num[fx],num[fy]);adde(num[fy],num[fx]);
        }
        mx=0;
        dfs(1,0,-1);
        mx=0;
        dfs(node,0,-1);
        cout<<cnt-1-mx<<endl;
    }
    return 0;
}

原文地址:https://www.cnblogs.com/heyuhhh/p/10393312.html

时间: 2024-10-17 00:57:30

HDU4612:Warm up(缩点+树的直径)的相关文章

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

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

hdu4612(双连通缩点+树的直径)

传送门:Warm up 题意:询问如何加一条边,使得剩下的桥的数目最少,输出数目. 分析:tarjan缩点后,重新建图得到一棵树,树上所有边都为桥,那么找出树的直径两个端点连上,必定减少的桥数量最多,因此ans=树的边数-树的直径. #pragma comment(linker,"/STACK:1024000000,1024000000") #include <cstdio> #include <cstring> #include <string>

codeforces GYM 100114 J. Computer Network 无相图缩点+树的直径

题目链接: http://codeforces.com/gym/100114 Description The computer network of “Plunder & Flee Inc.” consists of n servers and m two-way communication links. Two servers can communicate either through a direct link, or through a chain of links, by relayi

【HDU 4612 Warm up】BCC 树的直径

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4612 题意:一个包含n个节点m条边的无向连通图(无自环,可能有重边).求添加一条边后最少剩余的桥的数目. 思路:要想尽可能地消灭桥,那么添加的这条边一定是连通了最多的BCC. 所以首先进行双连通分量分解,并记录桥的数目:然后将同属一个BCC的点缩成一个,代之以block序号,以block序号为点将原图重构为一棵树. 最后求树的直径,桥的数目减去树的直径即为答案. 整体框架是学习了 http://w

Warm up---hdu4612(求树的直径)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4612 给一个无向图, 加上一条边后,求桥至少有几个: 那我们加的那条边的两个顶点u,v:一定是u,v之间含有桥的数量最多,然后uv之间的桥都没了,剩下的就是要求的结果: 树的直径的定义刚好就是两个节点之间含有最多的边: 下面是有关树的直径的知识: 这个题目需要手动扩展,不然会爆栈,而且手动扩展的话要用C++提交. #pragma comment(linker, "/STACK:1024000000,

Warm up——缩点、树上直径

题目链接 题意: 给出n个点和m条边的无向图,存在重边,问加一条边以后,剩下的桥的数量最少为多少. 题解: 把这个无向图缩点后会得到一个只由桥来连接的图(可以说这个图中的所有边都是桥,相当于一棵树), 然后我们只需要找出来这棵树的最大直径(即相距最远的两个点). 因为如果我们把直径所在的两个端点连起来,这样减少的桥最多. 所以 答案就是 桥的数量 - 树的直径上桥的数量 原图求桥的数量,缩点后建立新的图求直径 代码: #include <stdio.h> #include <string

Warm up HDU - 4612( 树的直径 边双连通分量)

求在图中新建一条边后  剩下的最少的桥的数量..先tarjan求桥的数量..然后缩点..以连通分量为点建图  bfs求直径 最后用桥的数量减去直径即为答案 bfs求直径 https://www.cnblogs.com/WTSRUVF/p/9307517.html #include <iostream> #include <cstdio> #include <cstring> #include <queue> #include <algorithm>

hdu4612 无向图中任意添加一条边后使桥的数量最少 / 无向图缩点+求树的直径

题意如上,含有重边(重边的话,俩个点就可以构成了边双连通). 先缩点成树,在求数的直径,最远的连起来,剩下边(桥)的自然最少.这里学习了树的直径求法:第一次选任意起点U,进行bfs,到达最远的一个点v(level最深)该点必然是树的直径的一个端点,,再从该点出发,bfs,到最深的一点,该点深度就是直径.(证明:先假设u,是直径上一点,S,T是直径的端点,设v!=t,则有(V,U)+(U,S)>(T,U)+(U,S),矛盾,故t=v:若u不是直径上一点,设u到直径上的一点为x,同理易证. 最后 缩

hdoj 4612 Warm up【双连通分量求桥&amp;&amp;缩点建新图求树的直径】

Warm up Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)Total Submission(s): 5093    Accepted Submission(s): 1131 Problem Description N planets are connected by M bidirectional channels that allow instant transport