题目链接: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. XGBoost原理学习总结

    XGBoost原理学习总结 前言 ​ XGBoost是一个上限提别高的机器学习算法,和Adaboost.GBDT等都属于Boosting类集成算法.虽然现在深度学习算法大行其道,但很多数据量往往没有太 ...

  2. 解决---MISCONF Redis被配置为保存RDB快照,但目前无法在磁盘上存留。可能修改数据集的命令被禁用。请检查Redis日志,了解有关错误的详细信息。

    解决---MISCONF Redis被配置为保存RDB快照,但目前无法在磁盘上存留.可能修改数据集的命令被禁用.请检查Redis日志,了解有关错误的详细信息. 出现bug: 在学习celery,将数据 ...

  3. Django设置session过期时间

    settings.py #session 设置 SESSION_COOKIE_AGE = 60 * 10 # 设置过期时间10分钟,默认为两周 SESSION_SAVE_EVERY_REQUEST = ...

  4. 【转载】计算机程序的思维逻辑 (82) - 理解ThreadLocal

    本节,我们来探讨一个特殊的概念,线程本地变量,在Java中的实现是类ThreadLocal,它是什么?有什么用?实现原理是什么?让我们接下来逐步探讨. 基本概念和用法 线程本地变量是说,每个线程都有同 ...

  5. 啥?你想diy一个智能音箱,来吧

    没错,这是智zhang语音助手 本系统基于自美系统二次开发,添加连接EMQ服务器,语音远程控制LED(Nodemcu),当然也可以扩展控制更多的设备,只需要将下位机设备连接到EMQ服务器即可. 由于使 ...

  6. CInternetSession的简单使用

    1. CInternetSession的简单使用 CInternetSession session; CHttpFile *file = NULL; CString strURL = " h ...

  7. 带大家用40行python代码实现一个疫情地图

    最近两个月,因为新冠病毒无情的肆虐,相信会给每个中国人的记忆中画上重重的一笔.到今天为止,疫情形势依然十分严峻,虽然除湖北外的其他省份已经连续十一天确诊人数下降,但是接下来还有将近至少1.6亿的人口迁 ...

  8. 登录sql sever

    MSSQLSEVER是默认的实例名,一台计算机可以安装多个实例名,相当于多个服务器,互不影响. workbench是MySQL 服务器的一个图形化管理客户端,功能类似于MySQL Command 安装 ...

  9. spyder学习记录---如何调试

    调试技巧: 当我们想单步执行某段代码(但是不进入调用的函数)时,点击运行当前行. 当我们想进入某个函数内部进行调试,在函数调用处点击进入函数或方法内运行. 当我们不想看函数内部的运行过程时,点击跳出函 ...

  10. 《C# 爬虫 破境之道》:第二境 爬虫应用 — 第四节:小说网站采集

    之前的章节,我们陆续的介绍了使用C#制作爬虫的基础知识,而且现在也应该比较了解如何制作一只简单的Web爬虫了. 本节,我们来做一个完整的爬虫系统,将之前的零散的东西串联起来,可以作为一个爬虫项目运作流 ...