HDU4612+Tarjan缩点+BFS求树的直径
tarjan+缩点+树的直径
题意:给出n个点和m条边的图,存在重边,问加一条边以后,剩下的桥的数量最少为多少。
先tarjan缩点,再在这棵树上求直径。加的边即是连接这条直径的两端。
1 /* 2 tarjan+缩点+树的直径 3 题意:给出n个点和m条边的图,存在重边,问加一条边以后,剩下的桥的数量最少为多少。 4 先tarjan缩点,再在这棵树上求直径。加的边即是连接这条直径的两端。 5 */ 6 #pragma comment(linker, "/STACK:1024000000,1024000000") 7 #include<stdio.h> 8 #include<string.h> 9 #include<stdlib.h> 10 #include<stack> 11 #include<algorithm> 12 #include<iostream> 13 #include<queue> 14 #include<map> 15 #include<math.h> 16 using namespace std; 17 typedef long long ll; 18 //typedef __int64 int64; 19 const int maxn = 300015; 20 const int maxm = 2000015; 21 const int inf = 0x7fffffff; 22 const double pi=acos(-1.0); 23 const double eps = 1e-8; 24 struct Edge{ 25 int v,next; 26 }edge[ maxm<<1 ],edgeTree[ maxm<<1 ]; 27 int cnt,cnt2,head[ maxn ],head2[ maxn ]; 28 int vis[ maxn ]; 29 int dfn[ maxn ]; 30 int low[ maxn ]; 31 int be[ maxn ];//缩点 32 int sum;//the num of "缩点" 33 int id; 34 stack<int>sta; 35 queue<int>q; 36 int maxNode,maxs;//这棵树的直径maxs 37 int dis[ maxn ]; 38 map<int,int>mp; 39 void init(){ 40 cnt = cnt2 = 0; 41 id = 0; 42 sum = 0; 43 //mp.clear(); 44 memset( head,-1,sizeof( head ) ); 45 memset( head2,-1,sizeof( head2 ) ); 46 memset( dfn,-1,sizeof( dfn ) ); 47 memset( vis,-1,sizeof( vis ) ); 48 memset( low,-1,sizeof( low ) ); 49 while( !sta.empty() ) 50 sta.pop(); 51 } 52 void addedge( int a,int b ){ 53 edge[ cnt ].v = b; 54 edge[ cnt ].next = head[ a ]; 55 head[ a ] = cnt++; 56 } 57 void addedge2( int a,int b ){ 58 edgeTree[ cnt2 ].v = b; 59 edgeTree[ cnt2 ].next = head2[ a ]; 60 head2[ a ] = cnt2++; 61 } 62 63 void tarjan( int u,int Link ){ 64 dfn[ u ] = low[ u ] = id++; 65 vis[ u ] = 1; 66 sta.push( u ); 67 int cc = 0; 68 for( int i=head[u];i!=-1;i=edge[i].next ){ 69 int v = edge[ i ].v; 70 if( dfn[ v ]==-1 ){ 71 tarjan( v,u ); 72 low[ u ] = min( low[ u ],low[ v ] ); 73 } 74 else if( Link==v ){ 75 if( cc ) low[ u ] = min( low[ u ],dfn[ v ] ); 76 cc++; 77 } 78 else if( vis[ v ]==1 ){ 79 low[ u ] = min( low[ u ],dfn[ v ] ); 80 } 81 } 82 if( dfn[u]==low[u] ){ 83 sum++; 84 int tt; 85 while( 1 ){ 86 tt = sta.top(); 87 sta.pop(); 88 vis[ tt ] = 0; 89 be[ tt ] = sum; 90 if( tt==u ) break; 91 } 92 } 93 } 94 void buildTree( int n ){ 95 for( int i=1;i<=n;i++ ){ 96 for( int j=head[ i ];j!=-1;j=edge[ j ].next ){ 97 if( be[i]!=be[edge[j].v] ){ 98 addedge2( be[i],be[edge[j].v] ); 99 } 100 } 101 } 102 } 103 void bfs( int s,int n ){ 104 memset( vis,0,sizeof( vis ) ); 105 vis[ s ] = 1; 106 while( !q.empty() ) 107 q.pop(); 108 q.push( s ); 109 dis[ s ] = 0; 110 maxs = 0; 111 while( !q.empty() ){ 112 int cur = q.front(); 113 q.pop(); 114 if( dis[ cur ]>=maxs ){ 115 maxs = dis[ cur ]; 116 maxNode = cur; 117 } 118 for( int i=head2[ cur ];i!=-1;i=edgeTree[ i ].next ){ 119 int v = edgeTree[ i ].v; 120 if( vis[ v ]==1 ) continue; 121 vis[ v ] = 1; 122 dis[ v ] = dis[ cur ]+1; 123 q.push( v ); 124 } 125 } 126 return ; 127 } 128 int dfs(int u,int p) 129 { 130 int max1=0,max2=0; 131 for (int i=head2[u];i!=-1;i=edgeTree[i].next) 132 { 133 int v=edgeTree[i].v; 134 if (v==p) continue; 135 int tmp=dfs(v,u)+1; 136 if (max1<tmp) max2=max1,max1=tmp; 137 else if (max2<tmp) max2=tmp; 138 } 139 maxs=max(maxs,max1+max2); 140 return max1; 141 } //dfs求树的直径 ok 142 int main(){ 143 int n,m; 144 while( scanf("%d%d",&n,&m)&&(n+m) ){ 145 int a,b; 146 init(); 147 while( m-- ){ 148 scanf("%d%d",&a,&b); 149 if( a==b ) continue; 150 //if( mp[min(a,b)] == max(a,b) ) continue; 151 //mp[min(a,b)] = max(a,b); 152 //不能这样去重边??? 153 addedge( a,b ); 154 addedge( b,a ); 155 } 156 for( int i=1;i<=n;i++ ){ 157 if( dfn[i]==-1 ){ 158 tarjan( i,-1 ); 159 } 160 } 161 buildTree( n ); 162 bfs( 1,sum ); 163 bfs( maxNode,sum ); 164 //printf("sum=%d, maxs=%d\n",sum,maxs); 165 //maxs = 0; 166 //dfs( 1,-1 ); 167 printf("%d\n",sum-1-maxs); 168 } 169 return 0; 170 }
View Code
转载于:https://www.cnblogs.com/xxx0624/p/3251907.html
HDU4612+Tarjan缩点+BFS求树的直径相关推荐
- 求树的直径+并查集(bfs,dfs都可以)hdu4514
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4514 这题主要是叫我们求出树的直径,在求树的直径之前要先判断一下有没有环 树的直径指的就是一棵树上面距 ...
- hdu 4607 Park Visit 求树的直径
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4607 Claire and her little friend, ykwd, are travelli ...
- 树上子链(树形dp求树的直径)
树上子链 题意: 给定一棵树 T ,树 T 上每个点都有一个权值. 定义一颗树的子链的大小为:这个子链上所有结点的权值和 . 请在树 T 中找出一条最大的子链并输出. 题解: 求树的直径,题目中存在负 ...
- Problem K. Road Network - ACPC2015(求树的直径 dp)
Problem K. Road Network 题目链接 Arab Collegiate Programming Contest 2015 题意: 树形的公路,如果阻塞道路可以断开两个区域彼此的连接, ...
- 求树的直径的两种方法
树的直径 树型dp求树的直径 优缺点: 优点为可以处理边权为负的情况,但不易得到直径的路径(指树的直径经过什么点). 代码模板: #include<bits/stdc++.h> using ...
- 《鲁滨逊漂流记》题解(LCA算法求树的直径)
Description <鲁滨逊漂流记>只讲到了鲁滨逊在岛上建立起一个自给自足的生态环境.而大家不知道的是,在此之后,鲁滨逊因为太无聊,开始探索周边的岛屿,一共 NNN 天.鲁滨逊第 11 ...
- F - Warm up - hdu 4612(缩点+求树的直径)
题意:有一个无向连通图,现在问添加一条边后最少还有几个桥 分析:先把图缩点,然后重构图为一棵树,求出来树的直径即可,不过注意会有重边,构树的时候注意一下 *********************** ...
- 求树的直径算法以及证明
以下为两次dfs(bfs)的做法以及正确性证明. 算法步骤 (1)任取树上一点S,以S为源点BFS得S到各个顶点的d值: (2)取d值最大者之一为P,再以P为源点BFS得P到各个顶点的d值: (3)再 ...
- 求树的直径(两种方法)
① 两次dfs 方法:先从任意一点P出发,找离它最远的点Q,再从点Q出发,找离它最远的点W,W到Q的距离就是是的直径 证明如下: ①若P已经在直径上,根据树的直径的定义可知Q也在直径上且为直径的一个端 ...
最新文章
- 仿站小工具8.0_安卓微信8.0版本可以升级了!新增4个实用功能,内附更新方式...
- JAVA _构造函数
- 72. Leetcode 99. 恢复二叉搜索树 (二叉搜索树-中序遍历类)
- Redis对象类型与编码
- Vue中组态实现方案-BaseMap的使用
- Java网页开发中model实现Serializable接口的原因
- 【LeetCode - 122】买卖股票的最佳时机 II(贪心 或 dp)
- 图形学 射线相交算法_计算机图形学中的阴极射线管(CRT)
- 再见 Spring Task,这个定时任务框架真香!
- Inter Thread Latency
- android 初始化类,Android 常用编程技巧/Java类的初始化顺序 (静态变量、静态初始化块、变量、初始化块、构造器)...
- java 事件监听应用_Spring Boot应用事件监听示例详解
- excel导出_学习笔记—— 前端导出excel
- winform窗体——布局方式
- 使用Notepad++编辑器查看二进制bin文件
- Mac本换ssd注意事项
- 眼睛又干又痒,到底是干眼症还是结膜炎?
- POJ - Nice Milk(半平面交)
- 一篇文章全面了解光纤到户FTTH,光分路器
- Kafka 发送消息 Idempotent
热门文章
- 用JAVA使用mysql命令操作导入SQL脚本
- RabbitMQ生产者和消费者Java实现
- Eclipse离线安装Emmet插件----web开发者绝对熟悉的插件之一
- java学习日记(1-7)
- Node.js使用supervisor遭遇‘supervisor’不是内部或外部命令,如果解决?
- 五大最主流浏览器综合性能测试
- ASP与ActiveX控件交互实战(一)
- java窗体加入声音_我用JAVA写好了一个窗体游戏,怎么加背景音乐?
- asa清空配置_Cisco ASA 管理配置文件
- Spring-core-SpringFactoriesLoader类