给你一个连通图,你可以任意加一条边,最小化桥的数目。


添加一条边,发现在边双内是不会减少桥的。只有在边双与边双之间加边才有效。于是,跑一遍边双并缩点,然后就变成一棵树,这样要加一条非树边,路径上的点(边双)就都变成一个大边双了,所以问题转化为求树上最长路径,跑直径即可。

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<algorithm>
  5. #include<cmath>
  6. #include<queue>
  7. #define mst(x) memset(x,0,sizeof x)
  8. #define dbg(x) cerr << #x << " = " << x <<endl
  9. #define dbg2(x,y) cerr<< #x <<" = "<< x <<" "<< #y <<" = "<< y <<endl
  10. using namespace std;
  11. typedef long long ll;
  12. typedef double db;
  13. typedef pair<int,int> pii;
  14. template<typename T>inline T _min(T A,T B){return A<B?A:B;}
  15. template<typename T>inline T _max(T A,T B){return A>B?A:B;}
  16. template<typename T>inline char MIN(T&A,T B){return A>B?(A=B,):;}
  17. template<typename T>inline char MAX(T&A,T B){return A<B?(A=B,):;}
  18. template<typename T>inline void _swap(T&A,T&B){A^=B^=A^=B;}
  19. template<typename T>inline T read(T&x){
  20. x=;int f=;char c;while(!isdigit(c=getchar()))if(c=='-')f=;
  21. while(isdigit(c))x=x*+(c&),c=getchar();return f?x=-x:x;
  22. }
  23. const int N=2e5+,M=1e6+;
  24. struct thxorz{int to,nxt;}G1[M<<],G2[N<<];
  25. int Head1[N],Head2[N],tot1,tot2;
  26. int n,m;
  27. inline void Addedge(int x,int y){
  28. G1[++tot1].to=y,G1[tot1].nxt=Head1[x],Head1[x]=tot1;
  29. G1[++tot1].to=x,G1[tot1].nxt=Head1[y],Head1[y]=tot1;
  30. }
  31. inline void Addtedge(int x,int y){
  32. G2[++tot2].to=y,G2[tot2].nxt=Head2[x],Head2[x]=tot2;
  33. G2[++tot2].to=x,G2[tot2].nxt=Head2[y],Head2[y]=tot2;
  34. }
  35. #define y G1[j].to
  36. int dfn[N],low[N],cut[M<<],cnt;
  37. void tarjan(int x,int i){
  38. dfn[x]=low[x]=++cnt;
  39. for(register int j=Head1[x];j;j=G1[j].nxt)if(j^(i^)){
  40. if(!dfn[y]){
  41. tarjan(y,j);MIN(low[x],low[y]);
  42. if(low[y]>dfn[x])cut[j]=cut[j^]=;
  43. }
  44. else MIN(low[x],dfn[y]);
  45. }
  46. }
  47. int bel[N],dcc;
  48. void dfs(int x){
  49. bel[x]=dcc;
  50. for(register int j=Head1[x];j;j=G1[j].nxt)if(!bel[y]&&!cut[j])dfs(y);
  51. }
  52. #undef y
  53. #define y G2[j].to
  54. int dep,pt;
  55. void tree_dfs(int x,int fa,int d){
  56. if(MAX(dep,d))pt=x;
  57. for(register int j=Head2[x];j;j=G2[j].nxt)if(y^fa)tree_dfs(y,x,d+);
  58. }
  59. #undef y
  60. int main(){//freopen("test.in","r",stdin);//freopen("test.ans","w",stdout);
  61. while(read(n),read(m),n||m){
  62. tot1=;dcc=tot2=cnt=dcc=;mst(Head1),mst(Head2),mst(dfn),mst(low),mst(cut),mst(bel);
  63. for(register int i=,x,y;i<=m;++i)read(x),read(y),Addedge(x,y);
  64. for(register int i=;i<=n;++i)if(!dfn[i])tarjan(i,);
  65. for(register int i=;i<=n;++i)if(!bel[i])++dcc,dfs(i);
  66. for(register int t=,u,v;t<=tot1;t+=){
  67. u=G1[t].to,v=G1[t^].to;
  68. if(bel[u]^bel[v])Addtedge(bel[u],bel[v]);//dbg2(bel[u],bel[v]);
  69. }
  70. dep=,tree_dfs(,,);dep=,tree_dfs(pt,,);
  71. printf("%d\n",dcc-dep);
  72. }
  73. return ;
  74. }

总结:和桥有关的可以首先考虑缩点建树,因为树有很好的性质,并且树边都是有桥连接起来的,同一个边双方便处理。

hdu4612 Warm up[边双连通分量缩点+树的直径]的更多相关文章

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

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

  2. HDU-4612 Warm up 边双连通分量+缩点+最长链

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4612 简单图论题,先求图的边双连通分量,注意,此题有重边(admin还逗比的说没有重边),在用targ ...

  3. Gym - 100676H H. Capital City (边双连通分量缩点+树的直径)

    https://vjudge.net/problem/Gym-100676H 题意: 给出一个n个城市,城市之间有距离为w的边,现在要选一个中心城市,使得该城市到其余城市的最大距离最短.如果有一些城市 ...

  4. HDU4612 Warm up 边双连通分量&&桥&&树直径

    题目的意思很简单,给你一个已经连通的无向图,我们知道,图上不同的边连通分量之间有一定数量的桥,题目要求的就是要你再在这个图上加一条边,使得图的桥数目减到最少. 首先要做的就是找出桥,以及每个点所各自代 ...

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

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

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

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

  7. hdu4612(双连通缩点+树的直径)

    传送门:Warm up 题意:询问如何加一条边,使得剩下的桥的数目最少,输出数目. 分析:tarjan缩点后,重新建图得到一棵树,树上所有边都为桥,那么找出树的直径两个端点连上,必定减少的桥数量最多, ...

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

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

  9. POJ3177 Redundant Paths(边双连通分量+缩点)

    题目大概是给一个无向连通图,问最少加几条边,使图的任意两点都至少有两条边不重复路径. 如果一个图是边双连通图,即不存在割边,那么任何两个点都满足至少有两条边不重复路径,因为假设有重复边那这条边一定就是 ...

随机推荐

  1. 一文带你了解babel-preset-env

    参考链接:https://www.jianshu.com/p/000c2670672b

  2. upw,c#,代码实现关闭,重启应用

    微软为uwp直接提供了这些API,可以很容易的直接进行调用 关闭 using Windows.ApplicationModel.Core; CoreApplication.Exit(); or usi ...

  3. GitLab中批量更换路径并保留历史记录

    git-change-path.sh #!/bin/bash cat git-name.txt | while read line do echo $line git clone --mirror g ...

  4. 粒子群算法(PSO)

    这几天看书的时候看到一个算法,叫粒子群算法,这个算法挺有意思的,下面说说我个人的理解: 粒子群算法(PSO)是一种进化算法,是一种求得近似最优解的算法,这种算法的时间复杂度可能会达到O(n!),得到的 ...

  5. pycharm配置git版本管理

    1.下载并安装git 首先你电脑必须安装git版本控制器(软件),在官网下载即可 2.安装git,正常安装即可 编缉器的选择,根据电脑实际情况选择合适的编缉器 安装参考:https://www.cnb ...

  6. Web文件上传靶场 - 通关笔记

    Web应用程序通常会提供一些上传功能,比如上传头像,图片资源等,只要与资源传输有关的地方就可能存在上传漏洞,上传漏洞归根结底是程序员在对用户文件上传时控制不足或者是处理的缺陷导致的,文件上传漏洞在渗透 ...

  7. 牛客 26E 珂学送分2 (状压dp)

    珂...珂...珂朵莉给你出了一道送分题: 给你一个长为n的序列{vi},和一个数a,你可以从里面选出最多m个数 一个合法的选择的分数定义为选中的这些数的和加上额外规则的加分: 有b个额外的规则,第i ...

  8. volatile 关键字(修饰变量)

    目录 volatile 关键字(修饰变量) 1. 含义 2. 作用 3. 如何保证可见性 4. 如何禁止指令重排序优化 5. volatile 是不安全的 6. volatile 不适用场景 vola ...

  9. JVM描述符标识字符含义

    标识字符 含义 B byte C char D double F float I int J long S short Z boolean V void L 对象类型,如Ljava/lang/Obje ...

  10. [NOIP10.4模拟赛]2.y题解--折半搜索+状压计数

    题目链接: 咕 闲扯: 这题暴力分似乎挺多,但是一些奇奇怪怪的细节没注意RE了,还是太菜了 分析: 首先我们考虑最naiive的状压DP ,\(f[u][v][state]\)表示u开头,v结尾是否存 ...