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

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

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

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

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

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <algorithm>
  4. #include <queue>
  5. #include <vector>
  6. using namespace std;
  7. #define pb push_back
  8.  
  9. const int N = (int)2e5+;
  10. const int M = (int)1e6+;
  11. int n,m,bridge,tot,tim,top,scc;
  12. int head[N],dfn[N],low[N],s[N],scc_no[N],vis[N];
  13. struct node{
  14. int to;
  15. int nxt;
  16. }e[M << ];
  17. vector<int> g[N];//新图
  18. vector<int> poi;//存单个连通图包含的点
  19.  
  20. void init(){
  21. for(int i = ; i <= n; ++i){
  22. head[i] = -;
  23. dfn[i] = ;
  24. g[i].clear();
  25. }
  26. bridge = tot = tim = top = scc = ;
  27. }
  28.  
  29. inline void add(int u,int v){
  30. e[tot].to = v;
  31. e[tot].nxt = head[u];
  32. head[u] = tot++;
  33. }
  34.  
  35. //tarjan缩点
  36. void tarjan(int now,int pre){
  37. poi.pb(now);//存下这个连通图包含的点
  38. dfn[now] = low[now] = ++tim;
  39. s[top++] = now;
  40. int to,pre_cnt = ;
  41. for(int o = head[now]; ~o; o = e[o].nxt){
  42. to = e[o].to;
  43. if(to == pre && pre_cnt == ) { pre_cnt = ; continue; }
  44. if(!dfn[to]){
  45. tarjan(to,now);
  46. low[now] = min(low[now],low[to]);
  47. if(dfn[now] < low[to]) ++bridge;
  48. }else low[now] = min(low[now],dfn[to]);
  49. }
  50.  
  51. if(dfn[now] == low[now]){
  52. int x;
  53. ++scc;
  54. do{
  55. x = s[--top];
  56. scc_no[x] = scc;
  57. }while(now != x);
  58. }
  59. }
  60.  
  61. //对poi中的那些点新建一个图
  62. void rebuild(){
  63. int to,now;
  64. for(int i = ; i < (int)poi.size(); ++i){
  65. now = poi[i];
  66. for(int o = head[now]; ~o; o = e[o].nxt){
  67. to = e[o].to;
  68. if(scc_no[now] == scc_no[to]) continue;
  69. g[scc_no[now]].pb(scc_no[to]); g[scc_no[to]].pb(scc_no[now]);
  70. }
  71. }
  72. }
  73.  
  74. void dfs(int now,int pre,int deep){
  75. vis[now] = deep;
  76. int to;
  77. for(int i = ; i < (int)g[now].size(); ++i){
  78. to = g[now][i];
  79. if(to == pre || to == now || vis[to]) continue;
  80. dfs(to,now,deep+);
  81. }
  82. }
  83.  
  84. void test01(){
  85. for(int i = ; i <= n; ++i)
  86. printf("%d 属于scc = %d\n",i,scc_no[i]);
  87. }
  88.  
  89. void solve(){
  90.  
  91. int max_deep = ,_deep = ;
  92. int u;
  93. for(int i = ; i <= n; ++i){
  94. if(!dfn[i]){
  95. poi.clear();//清空上个连通图中的点
  96. tarjan(i,i);
  97. rebuild();//poi中的点重建图
  98. dfs(poi[],poi[],);
  99. _deep = ;
  100. for(int i = ; i < poi.size(); ++i){
  101. if(_deep < vis[poi[i]]){ _deep = vis[poi[i]]; u = poi[i]; }
  102. vis[poi[i]] = ; //这里别忘了初始化 不然下次dfs会出错
  103. }
  104. dfs(u,u,);
  105. for(int i = ; i < poi.size(); ++i){
  106. _deep = max(_deep,vis[poi[i]]);
  107. vis[poi[i]] = ;//这里别忘了初始化 不然下组数据的dfs会出错
  108. }
  109. max_deep = max(max_deep,_deep);//对每个连通图跑两次dfs求树的直径,取max
  110. }
  111. }
  112. // cout << bridge << " " << max_deep << endl;
  113. printf("%d\n",bridge - max_deep +);
  114. }
  115.  
  116. int main(){
  117.  
  118. int u,v;
  119. while(~scanf("%d%d",&n,&m) && (n+m)){
  120. init();
  121. for(int i = ; i < m; ++i){
  122. scanf("%d%d",&u,&v);
  123. add(u,v); add(v,u);
  124. }
  125. solve();
  126. }
  127.  
  128. return ;
  129. }

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. 使用 CompletableFuture 异步组装数据

    使用 CompletableFuture 异步组装数据 一种快捷.优雅的异步组装数据方式 实际项目中经常遇到这种情况: 从多个表中查找到数据然后拼装成一个VO返回给前端. 这个过程有可能会非常耗时.因 ...

  2. object-c中的int NSInteger NSUInteger NSNumber辨析

    object-c中的int NSInteger NSUInteger NSNumber辨析 #import <Foundation/Foundation.h> int main(int a ...

  3. yum管理及源码安装

    一.配置YUM库及更新操作 yum概述 基于RPM包构建的软件更新机制,自动解决软件依赖关系 YUM仓库格式 本地:file:// 网络:ftp://或http:// yum源里面包含的内容 .rpm ...

  4. FFMPEG学习----使用SDL构建音频播放器

    ffmpeg版本:ffmpeg-20160413-git-0efafc5 #include <stdio.h> #include <stdlib.h> #include < ...

  5. 非常NB的一款快捷启动软件--Merry

    Merry 被设计为了能将日常重复性操作简化为一个快捷键或者命令.Merry 采用完全开放的体系, 可以使用 Lua 或者外部程序来扩展 Merry 的功能. 另附一个自己扩展的LUA脚本: --启动 ...

  6. Android之SimpleAdapter简单实例和SimpleAdapter参数说明

    SimpleAdapter基本上认知了其参数含义 用起来就简单多了 SimpleAdapter的参数说明 第一个参数 表示访问整个android应用程序接口,基本上所有的组件都需要  第二个参数表示生 ...

  7. Codeforces_540_C

    http://codeforces.com/problemset/problem/540/C 简单bfs,注意结束条件. #include<iostream> #include<cs ...

  8. 《C# 爬虫 破境之道》:第二境 爬虫应用 — 第五节:小总结带来的优化与重构

    在上一节中,我们完成了一个简单的采集示例.本节呢,我们先来小结一下,这个示例可能存在的问题: 没有做异常处理 没有做反爬应对策略 没有做重试机制 没有做并发限制 …… 呃,看似平静的表面下还是隐藏着不 ...

  9. 利用视频解析网站免费观看各大平台VIP电影

    需求: 观看VIP电影.VIP电视 准备: 1.视频解析网站 2.VIP电影URL 教程开始: 1.百度搜索[视频解析],会索引出大量的视频解析网站,随便选择一个网站. 2.找到想观看的VIP视频,复 ...

  10. c++算法:计算行列式的值(详细讲解)

    参考了:https://blog.csdn.net/u011885865/article/details/42032229 需要的基础:学过<线性代数>,知道行列式值的求法 基本公式:对于 ...