HDU4612+Tarjan缩点+BFS求树的直径
tarjan+缩点+树的直径
题意:给出n个点和m条边的图,存在重边,问加一条边以后,剩下的桥的数量最少为多少。
先tarjan缩点,再在这棵树上求直径。加的边即是连接这条直径的两端。
/*
tarjan+缩点+树的直径
题意:给出n个点和m条边的图,存在重边,问加一条边以后,剩下的桥的数量最少为多少。
先tarjan缩点,再在这棵树上求直径。加的边即是连接这条直径的两端。
*/
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<stack>
#include<algorithm>
#include<iostream>
#include<queue>
#include<map>
#include<math.h>
using namespace std;
typedef long long ll;
//typedef __int64 int64;
const int maxn = ;
const int maxm = ;
const int inf = 0x7fffffff;
const double pi=acos(-1.0);
const double eps = 1e-;
struct Edge{
int v,next;
}edge[ maxm<< ],edgeTree[ maxm<< ];
int cnt,cnt2,head[ maxn ],head2[ maxn ];
int vis[ maxn ];
int dfn[ maxn ];
int low[ maxn ];
int be[ maxn ];//缩点
int sum;//the num of "缩点"
int id;
stack<int>sta;
queue<int>q;
int maxNode,maxs;//这棵树的直径maxs
int dis[ maxn ];
map<int,int>mp;
void init(){
cnt = cnt2 = ;
id = ;
sum = ;
//mp.clear();
memset( head,-,sizeof( head ) );
memset( head2,-,sizeof( head2 ) );
memset( dfn,-,sizeof( dfn ) );
memset( vis,-,sizeof( vis ) );
memset( low,-,sizeof( low ) );
while( !sta.empty() )
sta.pop();
}
void addedge( int a,int b ){
edge[ cnt ].v = b;
edge[ cnt ].next = head[ a ];
head[ a ] = cnt++;
}
void addedge2( int a,int b ){
edgeTree[ cnt2 ].v = b;
edgeTree[ cnt2 ].next = head2[ a ];
head2[ a ] = cnt2++;
} void tarjan( int u,int Link ){
dfn[ u ] = low[ u ] = id++;
vis[ u ] = ;
sta.push( u );
int cc = ;
for( int i=head[u];i!=-;i=edge[i].next ){
int v = edge[ i ].v;
if( dfn[ v ]==- ){
tarjan( v,u );
low[ u ] = min( low[ u ],low[ v ] );
}
else if( Link==v ){
if( cc ) low[ u ] = min( low[ u ],dfn[ v ] );
cc++;
}
else if( vis[ v ]== ){
low[ u ] = min( low[ u ],dfn[ v ] );
}
}
if( dfn[u]==low[u] ){
sum++;
int tt;
while( ){
tt = sta.top();
sta.pop();
vis[ tt ] = ;
be[ tt ] = sum;
if( tt==u ) break;
}
}
}
void buildTree( int n ){
for( int i=;i<=n;i++ ){
for( int j=head[ i ];j!=-;j=edge[ j ].next ){
if( be[i]!=be[edge[j].v] ){
addedge2( be[i],be[edge[j].v] );
}
}
}
}
void bfs( int s,int n ){
memset( vis,,sizeof( vis ) );
vis[ s ] = ;
while( !q.empty() )
q.pop();
q.push( s );
dis[ s ] = ;
maxs = ;
while( !q.empty() ){
int cur = q.front();
q.pop();
if( dis[ cur ]>=maxs ){
maxs = dis[ cur ];
maxNode = cur;
}
for( int i=head2[ cur ];i!=-;i=edgeTree[ i ].next ){
int v = edgeTree[ i ].v;
if( vis[ v ]== ) continue;
vis[ v ] = ;
dis[ v ] = dis[ cur ]+;
q.push( v );
}
}
return ;
}
int dfs(int u,int p)
{
int max1=,max2=;
for (int i=head2[u];i!=-;i=edgeTree[i].next)
{
int v=edgeTree[i].v;
if (v==p) continue;
int tmp=dfs(v,u)+;
if (max1<tmp) max2=max1,max1=tmp;
else if (max2<tmp) max2=tmp;
}
maxs=max(maxs,max1+max2);
return max1;
} //dfs求树的直径 ok
int main(){
int n,m;
while( scanf("%d%d",&n,&m)&&(n+m) ){
int a,b;
init();
while( m-- ){
scanf("%d%d",&a,&b);
if( a==b ) continue;
//if( mp[min(a,b)] == max(a,b) ) continue;
//mp[min(a,b)] = max(a,b);
//不能这样去重边???
addedge( a,b );
addedge( b,a );
}
for( int i=;i<=n;i++ ){
if( dfn[i]==- ){
tarjan( i,- );
}
}
buildTree( n );
bfs( ,sum );
bfs( maxNode,sum );
//printf("sum=%d, maxs=%d\n",sum,maxs);
//maxs = 0;
//dfs( 1,-1 );
printf("%d\n",sum--maxs);
}
return ;
}
HDU4612+Tarjan缩点+BFS求树的直径的更多相关文章
- HDU-4612 Warm up,tarjan求桥缩点再求树的直径!注意重边
Warm up 虽然网上题解这么多,感觉写下来并不是跟别人竞争访问量的,而是证明自己从前努力过,以后回头复习参考! 题意:n个点由m条无向边连接,求加一条边后桥的最少数量. 思路:如标题,tarjan ...
- 4612 warm up tarjan+bfs求树的直径(重边的强连通通分量)忘了写了,今天总结想起来了。
问加一条边,最少可以剩下几个桥. 先双连通分量缩点,形成一颗树,然后求树的直径,就是减少的桥. 本题要处理重边的情况. 如果本来就两条重边,不能算是桥. 还会爆栈,只能C++交,手动加栈了 别人都是用 ...
- [USACO2004][poj1985]Cow Marathon(2次bfs求树的直径)
http://poj.org/problem?id=1985 题意:就是给你一颗树,求树的直径(即问哪两点之间的距离最长) 分析: 1.树形dp:只要考虑根节点和子节点的关系就可以了 2.两次bfs: ...
- 牛客小白月赛6C-桃花(DFS/BFS求树的直径)
链接:https://www.nowcoder.com/acm/contest/136/C 来源:牛客网 桃花 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语言 ...
- 两次bfs求树的直径的正确性
结论:离树上任意点\(u\)最远的点一定是这颗树直径的一个端点. 证明: 若点\(u\)在树的直径上,设它与直径两个端点\(x,y\)的距离分别为\(S1\).\(S2\),若距离其最远的点\(v\) ...
- hdoj 4612 Warm up【双连通分量求桥&&缩点建新图求树的直径】
Warm up Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others)Total Su ...
- 求树的直径+并查集(bfs,dfs都可以)hdu4514
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4514 这题主要是叫我们求出树的直径,在求树的直径之前要先判断一下有没有环 树的直径指的就是一棵树上面距 ...
- 洛谷 P3627 [APIO2009]抢掠计划 Tarjan缩点+Spfa求最长路
题目地址:https://www.luogu.com.cn/problem/P3627 第一次寒假训练的结测题,思路本身不难,但对于我这个码力蒟蒻来说实现难度不小-考试时肛了将近两个半小时才刚肛出来. ...
- (求树的直径)Warm up -- HDU -- 4612
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4612 给一个无向图, 加上一条边后,求桥至少有几个: 那我们加的那条边的两个顶点u,v:一定是u,v之 ...
随机推荐
- Android EditText不弹出输入法焦点问题的总结
转自:http://mobile.51cto.com/aprogram-403138.htm 看一个manifest中Activity的配置,如果这个页面有EditText,并且我们想要进入这个页面的 ...
- NS-Date/NSDateFormatter
// // main.m // NS-Date // // Created by qianfeng on 15/6/23. // Copyright (c) 2015年 qianfeng. All r ...
- (转) Crittercism: 在MongoDB上实现每天数十亿次请求
MongoDB的扩展能力可以满足你业务需求的增长——这也是为什么它的名字来源于单词humongous(极大的)的原因.当然,这并不是说你在 使用MongoDB的路上并不会碰到一些发展的痛点.Critt ...
- (转)推荐一个在Linux/Unix上架设ASP.NET的 WEB服务器--Jexus
在Linux/Unix上架设ASP.NET WEB服务器,有两个可选方式,一种是Mono+XSP,一种是Mono+Jexus,其它的方式,比如 Apache+mod_mono.Nginx+FastCg ...
- String 转Clob
把String转Clob java.sql.Clob c = new javax.sql.rowset.serial.SerialClob("abc".toCharArray())
- From MSI to WiX, Part 4 - Features and Components by Alex Shevchuk
Following content is directly reprinted from : http://blogs.technet.com/b/alexshev/archive/2008/08/2 ...
- CICS日志---内存问题
Level 9 COCITOOL_XA: Connected! [2014-01-09 19:46:24.296834][22347888] Level 0 TestPerormence: GDAO ...
- C++四种强制类型转换关键字
C语言使用强制类型转换(Type Cast)很简单,不管什么类型的转换,形式都如下: TYPE b = (TYPE)a; c++提供了4种类型转换操作符来应对不同场合的应用. const_cast ...
- 如何管好.net的内存(托管堆和垃圾回收)
一:C#标准Dispose模式的实现 需要明确一下C#程序(或者说.NET)中的资源.简单的说来,C#中的每一个类型都代表一种资源,而资源又分为两类: 托管资源:由CLR管理分配和释放的资源,即由CL ...
- 手机淘宝用JS来动态写meta标签(1像素边框处理方法)
var metaEl = doc.createElement('meta'); var scale = isRetina ? 0.5:1; metaEl.setAttribute('name', 'v ...