题目链接

Warm up

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

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
给一个图, 求增加一条边之后的桥的数量最少是多少。有重边
 
缩点然后找树的直径, 答案就是缩点之后的边数-直径。
tarjan的时候注意, vis数组记录访问过的边的编号而不是点。
找树的直径最好写bfs, dfs据说爆栈
详细看代码。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
using namespace std;
#define mem(a) memset(a, 0, sizeof(a))
#define mem1(a) memset(a, -1, sizeof(a))
#define mem2(a) memset(a, 0x3f, sizeof(a))
#define fi first
#define se second
typedef pair<int, int> pll;
const int inf = ;
const int maxn = 2e5+;
const int maxe = 1e6+;
int head[maxn], head1[maxn], dis[maxn], num, num1, top, cnum, instack[maxn], st[maxn], dfn[maxn], low[maxn], s[maxn];
int maxx, pos, vis[maxe*], cnt;
struct node
{
int to, nextt;
}e[maxe*], e1[maxe*];
void add(int u, int v) {
e[num].to = v, e[num].nextt = head[u], head[u] = num++;
}
void add1(int u, int v) {
e1[num1].to = v, e1[num1].nextt = head1[u], head1[u] = num1++;
}
void init() {
num = num1 = cnt = cnum = top = ;
mem1(head);
mem(s);
mem(vis);
mem1(head1);
mem(instack);
mem(st);
mem(dfn);
mem(low);
mem(dis);
}
pll edge[maxe];
void tarjan(int u) {
instack[u] = ;
st[top++] = u;
dfn[u] = low[u] = ++cnt;
for(int i = head[u]; ~i; i = e[i].nextt) {
int v = e[i].to;
if(vis[i])
continue;
vis[i] = vis[i^] = ;
if(!dfn[v]) {
tarjan(v);
low[u] = min(low[u], low[v]);
} else if(instack[v]) {
low[u] = min(low[u], dfn[v]);
}
}
if(low[u] == dfn[u]) {
++cnum;
int x;
do {
x = st[--top];
instack[x] = ;
s[x] = cnum;
} while(x != u);
}
}
void bfs(int u) {
queue <int> q;
q.push(u);
mem2(dis);
dis[u] = ;
mem(vis);
vis[u] = ;
maxx = , pos = u;
while(!q.empty()) {
int v = q.front(); q.pop();
for(int i = head1[v]; ~i; i = e1[i].nextt) {
int ve = e1[i].to;
if(vis[ve])
continue;
vis[ve] = ;
dis[ve] = dis[v]+;
if(dis[ve]>maxx) {
maxx = dis[ve];
pos = ve;
}
q.push(ve);
}
}
}
int main()
{
int n, m, x, y;
while(cin>>n>>m) {
if(n+m==)
break;
init();
for(int i = ; i<m; i++) {
scanf("%d%d", &x, &y);
edge[i].fi = x, edge[i].se = y;
add(x, y);
add(y, x);
}
tarjan();
int edgenum = ;
for(int i = ; i<m; i++) {
int x = edge[i].fi, y = edge[i].se;
if(s[x]!=s[y]) {
add1(s[x], s[y]);
add1(s[y], s[x]);
edgenum++;
}
}
bfs(s[]);
bfs(pos);
int ans = edgenum-maxx;
printf("%d\n", ans);
}
return ;
}

hdu 4612 Warm up 有重边缩点+树的直径的更多相关文章

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

    首先双连通缩点建立新图(顺带求原图的总的桥数,事实上因为原图是一个强连通图,所以桥就等于缩点后的边) 此时得到的图类似树结构,对于新图求一次直径,也就是最长链. 我们新建的边就一定是连接这条最长链的首 ...

  2. Hdu 4612 Warm up (双连通分支+树的直径)

    题目链接: Hdu 4612 Warm up 题目描述: 给一个无向连通图,问加上一条边后,桥的数目最少会有几个? 解题思路: 题目描述很清楚,题目也很裸,就是一眼看穿怎么做的,先求出来双连通分量,然 ...

  3. HDU 4612 Warm up(双连通分量缩点+求树的直径)

    思路:强连通分量缩点,建立一颗新的树,然后求树的最长直径,然后加上一条边能够去掉的桥数,就是直径的长度. 树的直径长度的求法:两次bfs可以求,第一次随便找一个点u,然后进行bfs搜到的最后一个点v, ...

  4. HDU 4612 Warm up 连通图缩点

    题目大意:给出一个连通图,求再一个边后,剩余的最少桥数. 题目思路:首先进行缩点得到重构后的图,求出重构后树的直径(通过两次BFS求出相距最远的两点间的距离),ans=重构图边数-树的直径 //#pr ...

  5. F - Warm up HDU - 4612 tarjan缩点 + 树的直径 + 对tajan的再次理解

    题目链接:https://vjudge.net/contest/67418#problem/F 题目大意:给你一个图,让你加一条边,使得原图中的桥尽可能的小.(谢谢梁学长的帮忙) 我对重边,tarja ...

  6. HDU 4612 Warm up —— (缩点 + 求树的直径)

    题意:一个无向图,问建立一条新边以后桥的最小数量. 分析:缩点以后,找出新图的树的直径,将这两点连接即可. 但是题目有个note:两点之间可能有重边!而用普通的vector保存边的话,用v!=fa的话 ...

  7. HDU 4612 Warm up (边双连通分量+缩点+树的直径)

    <题目链接> 题目大意:给出一个连通图,问你在这个连通图上加一条边,使该连通图的桥的数量最小,输出最少的桥的数量. 解题分析: 首先,通过Tarjan缩点,将该图缩成一颗树,树上的每个节点 ...

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

    Warm up Time Limit:5000MS     Memory Limit:65535KB     64bit IO Format:%I64d & %I64u Submit Stat ...

  9. 【HDU 4612 Warm up】BCC 树的直径

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4612 题意:一个包含n个节点m条边的无向连通图(无自环,可能有重边).求添加一条边后最少剩余的桥的数 ...

随机推荐

  1. JS onkeydown控制HTML Input 只录入浮点数值

    // -1) return false; return index == 0 } keychar = String.fromCharCode(keynum) var newVal = oriVal.s ...

  2. JqueryEasyUI中combox的数据不显示

    在做一个用jeasyui做的项目中遇到一个问题,对应的数据取出来了但是数据项一直出不来后来经过检查原来是赋值的时候对应的数组元素的名称写的有问题,以后一定要注意对应的问题,不能犯类似的错误 funct ...

  3. bootstrap的导航改造

    在使用bootstrap制作后台时用到了响应式导航条,其中dropdown组件更是用的比较多,用的多需要点击的就多,dropdown默认鼠标左键单击才展开,如果使用鼠标放上去(hover)就展开则会省 ...

  4. 【转】使用Navicat for Oracle新建表空间、用户及权限赋予

    首先.我们来新建一个表空间.打开Navicat for Oracle,输入相关的的连接信息.如下图: 填入正确的信息,连接后.我们点击面板上的“其他”下的选项“表空间”,如下图: 进入表空间的界面,我 ...

  5. ssh框架用JUnit测试

    public class testAuxDict { //读spring配置文件 public static BeanFactory factory = new ClassPathXmlApplica ...

  6. CentOs 安装 Nginx + php + mysql (推荐方式)

    本文全部采用yum进行安装, CentOs6.5 mini 版本. 一.更改yum源为网易的源加快速度, 如果是从网易镜像下载的安装包,直接注释这几项也可以 vim /etc/yum.repos.d/ ...

  7. Javascript中的attribute和property分析

    attribute和property这两个单词,都有属性的意思,attribute有属性.特质的意思,property则有性质,性能的意思. 首先需要明确的是,在规范中,读取和设置attribute的 ...

  8. 《离散数学之把妹要诀》的js实现

    网上看到一篇有意思的文章<离散数学之把妹要诀> 就用JS写了上面所讲的配对方式: 首先设定变量 // 男生理想列表 var menPreference = { A: [1, 2, 3, 4 ...

  9. PHP静态成员变量和非静态成员变量

    数据成员可以分静态变量.非静态变量两种. 静态成员: 静态类中的成员加入static修饰符,即是静态成员.可以直接使用类名+静态成员名访问此静态成员,因为静态成员存在于内存,非静态成员需要实例化才会 ...

  10. hdu 4676 Sum Of Gcd 莫队+数论

    题目链接 给n个数, m个询问, 每个询问给出[l, r], 问你对于任意i, j.gcd(a[i], a[j]) L <= i < j <= R的和. 假设两个数的公约数有b1, ...