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之 ...
随机推荐
- 我的博客已搬迁到http://www.lsworks.net
我的博客已搬迁到http://www.lsworks.net
- 动态linq表达式新方法,Dynamic LINQ Extension Method
Remember those old posts on Dynamic LINQ? You are probably aware that Microsoft has made its impleme ...
- 《PHP扩展开发及内核应用》
https://github.com/walu/phpbook/blob/master/preface.md
- artdialog 提示 确定或取消
dialog({ title:'提示', content:"下载需扣除" + point + "个积分<br />重复下载不扣积分,需要继续吗?", ...
- HTML5 内联框架iFrame
由于现在frame和frameset很少使用,已经过时了,已经被div+CSS代替了,所以,这里只是举例说明一下,当下还在使用的内联框架iFrame 所谓的iFrame内联框架,我的理解就是在网页内部 ...
- python(三)一个文件读写操作的小程序
我们要实现一个文件读写操作的小程序 首先我们有一个文件 我们要以"============"为界限,每一个角色分割成一个独立的txt文件,按照分割线走的话是分成 xiaoNa_1. ...
- linux计划任务运行php文件的方法分享
在linux下,借助crontab,设置计划任务每天6点10分执行filename.php文件,写入一行时间到log日志中. 创建计划任务的脚本: dos2unix /path/to/filename ...
- Python字符串内建处理函数
#coding=utf-8 __author__ = 'Administrator' # 字符串处理函数 s1 = "study python string function , I lov ...
- Perl中的正则表达
前几天用到了Perl语言,主要看了一下Perl中的正则表达式,在各种网页语言中,正则表达式在处理字符串的时候十分有用,所以这里就简单说一下在Perl中正则表达式的应用. 先上代码 #!/usr/bin ...
- win10 安装scrapy
在win10的环境下安装scrapy,并不能直接按照官网的手册(http://doc.scrapy.org/en/1.0/intro/install.html)一次性安装成功,根据我自己的安装过程中遇 ...