题目链接:https://vjudge.net/problem/HDU-4612

题目:一个大地图,给定若干个连通图,每个连通图中有若干个桥,你可以在任意某个连通图的

任意两个点添加一条边,问,添加一条边后,大地图中最少剩下几个桥。

思路:tarjan缩点,重构图,对每个新图跑两次dfs求出树的直径,取所有新图的直径max,

答案就是  大地图总桥数 - max(树的直径)。

 #include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
#define pb push_back const int N = (int)2e5+;
const int M = (int)1e6+;
int n,m,bridge,tot,tim,top,scc;
int head[N],dfn[N],low[N],s[N],scc_no[N],vis[N];
struct node{
int to;
int nxt;
}e[M << ];
vector<int> g[N];//新图
vector<int> poi;//存单个连通图包含的点 void init(){
for(int i = ; i <= n; ++i){
head[i] = -;
dfn[i] = ;
g[i].clear();
}
bridge = tot = tim = top = scc = ;
} inline void add(int u,int v){
e[tot].to = v;
e[tot].nxt = head[u];
head[u] = tot++;
} //tarjan缩点
void tarjan(int now,int pre){
poi.pb(now);//存下这个连通图包含的点
dfn[now] = low[now] = ++tim;
s[top++] = now;
int to,pre_cnt = ;
for(int o = head[now]; ~o; o = e[o].nxt){
to = e[o].to;
if(to == pre && pre_cnt == ) { pre_cnt = ; continue; }
if(!dfn[to]){
tarjan(to,now);
low[now] = min(low[now],low[to]);
if(dfn[now] < low[to]) ++bridge;
}else low[now] = min(low[now],dfn[to]);
} if(dfn[now] == low[now]){
int x;
++scc;
do{
x = s[--top];
scc_no[x] = scc;
}while(now != x);
}
} //对poi中的那些点新建一个图
void rebuild(){
int to,now;
for(int i = ; i < (int)poi.size(); ++i){
now = poi[i];
for(int o = head[now]; ~o; o = e[o].nxt){
to = e[o].to;
if(scc_no[now] == scc_no[to]) continue;
g[scc_no[now]].pb(scc_no[to]); g[scc_no[to]].pb(scc_no[now]);
}
}
} void dfs(int now,int pre,int deep){
vis[now] = deep;
int to;
for(int i = ; i < (int)g[now].size(); ++i){
to = g[now][i];
if(to == pre || to == now || vis[to]) continue;
dfs(to,now,deep+);
}
} void test01(){
for(int i = ; i <= n; ++i)
printf("%d 属于scc = %d\n",i,scc_no[i]);
} void solve(){ int max_deep = ,_deep = ;
int u;
for(int i = ; i <= n; ++i){
if(!dfn[i]){
poi.clear();//清空上个连通图中的点
tarjan(i,i);
rebuild();//poi中的点重建图
dfs(poi[],poi[],);
_deep = ;
for(int i = ; i < poi.size(); ++i){
if(_deep < vis[poi[i]]){ _deep = vis[poi[i]]; u = poi[i]; }
vis[poi[i]] = ; //这里别忘了初始化 不然下次dfs会出错
}
dfs(u,u,);
for(int i = ; i < poi.size(); ++i){
_deep = max(_deep,vis[poi[i]]);
vis[poi[i]] = ;//这里别忘了初始化 不然下组数据的dfs会出错
}
max_deep = max(max_deep,_deep);//对每个连通图跑两次dfs求树的直径,取max
}
}
// cout << bridge << " " << max_deep << endl;
printf("%d\n",bridge - max_deep +);
} int main(){ int u,v;
while(~scanf("%d%d",&n,&m) && (n+m)){
init();
for(int i = ; i < m; ++i){
scanf("%d%d",&u,&v);
add(u,v); add(v,u);
}
solve();
} return ;
}

4 4
1 2
1 3
1 4
2 3

11 12
1 2
1 3
3 2
3 4
4 5
4 6
6 7
7 8
7 9
8 9
8 11
9 10

6 7
1 2
1 3
2 3
3 4
4 5
4 6
5 6

8 6
1 2
1 3
1 4
1 5
7 6
6 8

kuangbin专题 专题九 连通图 Warm up HDU - 4612的更多相关文章

  1. kuangbin专题 专题九 连通图 Strongly connected HDU - 4635

    题目链接:https://vjudge.net/problem/HDU-4635 题目:有向图,给定若干个连通图,求最多还能添加几条边,添完边后,图仍然要满足 (1)是简单图,即没有重边或者自环 (2 ...

  2. F - Warm up - hdu 4612(缩点+求树的直径)

    题意:有一个无向连通图,现在问添加一条边后最少还有几个桥 分析:先把图缩点,然后重构图为一棵树,求出来树的直径即可,不过注意会有重边,构树的时候注意一下 *********************** ...

  3. (求树的直径)Warm up -- HDU -- 4612

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4612 给一个无向图, 加上一条边后,求桥至少有几个: 那我们加的那条边的两个顶点u,v:一定是u,v之 ...

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

    求在图中新建一条边后  剩下的最少的桥的数量..先tarjan求桥的数量..然后缩点..以连通分量为点建图  bfs求直径 最后用桥的数量减去直径即为答案 bfs求直径 https://www.cnb ...

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

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

  6. Warm up HDU - 4612 树的直径

    题意:给出n个点和m条边的无向图,存在重边,问加一条边以后,剩下的桥的数量最少为多少. 题解: 你把这个无向图缩点后会得到一个只由桥来连接的图(可以说这个图中的所有边都是桥,相当于一棵树),然后我们只 ...

  7. [kuangbin带你飞]专题九 连通图

        ID Origin Title   76 / 163 Problem A POJ 1236 Network of Schools   59 / 177 Problem B UVA 315 Ne ...

  8. 「kuangbin带你飞」专题十九 矩阵

    layout: post title: 「kuangbin带你飞」专题十九 矩阵 author: "luowentaoaa" catalog: true tags: mathjax ...

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

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

随机推荐

  1. 《即时消息技术剖析与实战》学习笔记9——IM系统如何支持消息的多终端漫游

    一.什么是多终端漫游 多终端漫游是指:用户在任意一个设备登录后,都能获取到历史的聊天记录.如:QQ 默认漫游 7 天的聊天记录,开通 VIP 会员可漫游 30 天,开通 SVIP 会员可漫游 2 年. ...

  2. JS基础——ATM机终端程序编写(2.0)

    在1.0版本上,利用数组进行用户的创建,通过调用数组下标,进行密码.余额的使用.新增了切换账户.修改密码的功能 以下为数组版代码. 创建模拟账户 个账户: let user = ["xiao ...

  3. Docker(一) 简介

    简介 Docker是一款针对程序开发人员和系统管理员来开发.部署.运行应用的一款虚拟化平台.Docker 可以让你像使用集装箱一样快速的组合成应用,并且可以像运输标准集装箱一样,尽可能的屏蔽代码层面的 ...

  4. Kotlin DSL for HTML实例解析

    Kotlin DSL for HTML实例解析 Kotlin DSL, 指用Kotlin写的Domain Specific Language. 本文通过解析官方的Kotlin DSL写html的例子, ...

  5. 脚本在Shell可以执行成功,放到crontab里执行失败

    一.背景 自己写了个监控MGR状态的脚本,直接在Linux的Shell环境下可以执行成功,但是只要放到crontab里执行,就失败,脚本内容如下 #!/bin/bash MAIL_ADDR=`cat ...

  6. Java类加载器和双亲委派机制

    前言 之前详细介绍了Java类的整个加载过程(类加载机制详解).虽然,篇幅较长,但是也不要被内容吓到了,其实每个阶段都可以用一句话来概括. 1)加载:查找并加载类的二进制字节流数据. 2)验证:保证被 ...

  7. 程序为什么开头总是PUSH EBP

    因为对堆栈的操作寄存器有EBP和ESP两个.EBP是堆栈的基址,ESP一直指向栈顶(只要有PUSH动作,ESP就自动减小,栈的生长方向从大往小,不需要手动改变ESP.)所以要压入EBP,然后再用EBP ...

  8. 使用自环接口的UDP服务器和客户端

    import argparse,socket from datetime import datetime MAX_BYTES = 65535 def server(port): sock = sock ...

  9. VMware复制Linux虚拟机后网络配置

    1.启动虚拟机,点击我已复制 点击已复制后,VMware将会为重置虚拟机网卡mac地址. 2.修改网卡mac地址 3.ifconfig显示网卡名称与配置不一致处理 Centos6中ifconfig显示 ...

  10. PHP5.3的VC9、VC6、Thread Safe、Non Thread Safe的区别

    PHP一共给了四个版本,VC9 x86 Non Thread Safe.VC9 x86 Thread Safe.VC6 x86 Non Thread Safe.VC6 x86 Thread Safe, ...