题目链接

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. android的Home键的监听封装工具类(一)

    android的Home键的监听封装: package com.gzcivil.utils; import android.content.BroadcastReceiver; import andr ...

  2. 解读机器学习基础概念:VC维的来龙去脉 | 数盟

    http://dataunion.org/14581.html

  3. EC读书笔记系列之5:条款9、条款10

    条款9 绝不在构造和析构过程中调用virtual函数 记住: ★在构造和析构期间不要调用virtual函数,∵这类调用从不下降至derived class ---------------------- ...

  4. leetcode Swap Nodes in Pairs python

    # Definition for singly-linked list. # class ListNode(object): # def __init__(self, x): # self.val = ...

  5. QF——iOS第三方登录和社会化分享

    QQ登录的流程: 1.下载SDK,并添加到项目中: 2.添加SDK需要的依赖库,以及配置文件: 3.重写APPDelegate的方法handleOpenURL和openURL: 4.实现Tencent ...

  6. <s:if>标签与ActionContext.getContext().getSession()

    今天在做<s:if>标签中的属性值从 ActionContext.getContext().getSession().put("WW_TRANS_I18N_LOCALE" ...

  7. struts2中#,$,%的用法以及el,ognl表达式的用法

    OGNL, JSTL, STRUTS2标签中符号#,$,%的用法示例 取Session中的值 <c:out value="${sessionScope.user.userId}&quo ...

  8. Nginx与Tomcat安装、配置与优化

    Nginx与Tomcat安装.配置与优化 Nginx与Tomcat安装.配置与优化 Nginx的安装与使用 Nginx是一款优秀的反向代理服务器 安装: rpm(或者是pkg安装),是预编译好的程序包 ...

  9. hadoop笔记之Hive入门(什么是Hive)

    Hive入门(一) Hive入门(一) 什么是Hive? Hive是个数据仓库,数据仓库就是数据库,但又与一般意义上的数据库有点区别 实际上,Hive是构建在hadoop HDFS上的一个数据仓库. ...

  10. jquery写的tab切换效果 非常简单

    自己写的一款 tab切换效果,比较简单,适合新手 <style type="text/css">*{margin:0; padding:0; font-size:12p ...