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求树的直径的更多相关文章

  1. HDU-4612 Warm up,tarjan求桥缩点再求树的直径!注意重边

    Warm up 虽然网上题解这么多,感觉写下来并不是跟别人竞争访问量的,而是证明自己从前努力过,以后回头复习参考! 题意:n个点由m条无向边连接,求加一条边后桥的最少数量. 思路:如标题,tarjan ...

  2. 4612 warm up tarjan+bfs求树的直径(重边的强连通通分量)忘了写了,今天总结想起来了。

    问加一条边,最少可以剩下几个桥. 先双连通分量缩点,形成一颗树,然后求树的直径,就是减少的桥. 本题要处理重边的情况. 如果本来就两条重边,不能算是桥. 还会爆栈,只能C++交,手动加栈了 别人都是用 ...

  3. [USACO2004][poj1985]Cow Marathon(2次bfs求树的直径)

    http://poj.org/problem?id=1985 题意:就是给你一颗树,求树的直径(即问哪两点之间的距离最长) 分析: 1.树形dp:只要考虑根节点和子节点的关系就可以了 2.两次bfs: ...

  4. 牛客小白月赛6C-桃花(DFS/BFS求树的直径)

    链接:https://www.nowcoder.com/acm/contest/136/C 来源:牛客网 桃花 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语言 ...

  5. 两次bfs求树的直径的正确性

    结论:离树上任意点\(u\)最远的点一定是这颗树直径的一个端点. 证明: 若点\(u\)在树的直径上,设它与直径两个端点\(x,y\)的距离分别为\(S1\).\(S2\),若距离其最远的点\(v\) ...

  6. hdoj 4612 Warm up【双连通分量求桥&&缩点建新图求树的直径】

    Warm up Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)Total Su ...

  7. 求树的直径+并查集(bfs,dfs都可以)hdu4514

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4514 这题主要是叫我们求出树的直径,在求树的直径之前要先判断一下有没有环 树的直径指的就是一棵树上面距 ...

  8. 洛谷 P3627 [APIO2009]抢掠计划 Tarjan缩点+Spfa求最长路

    题目地址:https://www.luogu.com.cn/problem/P3627 第一次寒假训练的结测题,思路本身不难,但对于我这个码力蒟蒻来说实现难度不小-考试时肛了将近两个半小时才刚肛出来. ...

  9. (求树的直径)Warm up -- HDU -- 4612

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4612 给一个无向图, 加上一条边后,求桥至少有几个: 那我们加的那条边的两个顶点u,v:一定是u,v之 ...

随机推荐

  1. 第一章、C#委托和事件(Delegate、Event、EventHandler、EventArgs)

    第一章.C#委托和事件(Delegate.Event.EventHandler.EventArgs) 分类: 学习笔记-C#网络编程2012-12-08 14:10 7417人阅读 评论(3) 收藏  ...

  2. 接口(interface)

    接口(interface) 接口(interface)定义了一个可由类和结构实现的协定.接口可以包含方法.属性.事件和索引器.接口不提供它所定义的成员的实现-它仅指定实现该接口的类或结构必须提供的成员 ...

  3. 【HTML 5或CSS3入门教程】找兼职撰写人才

    出版社要出版一套HTML 5和CSS 3方向的图书,目前急缺两名写作人员,要求1.熟悉CSS 3的各种属性,或熟悉HTML 5框架2.熟悉各种CSS代码,或熟悉各种HTML 5代码3.有写作的兴趣爱好 ...

  4. Alluxio1.0.1最新版(Tachyon为其前身)介绍,+HDFS分布式环境搭建

    Alluxio(之前名为Tachyon)是世界上第一个以内存为中心的虚拟的分布式存储系统.它统一了数据访问的方式,为上层计算框架和底层存储系统构建了桥梁. 应用只需要连接Alluxio即可访问存储在底 ...

  5. NOSQL之【redis的主从复制】

    一.Redis的Replication: 下面的列表清楚的解释了Redis Replication的特点和优势.    1). 同一个Master可以同步多个Slaves.    2). Slave同 ...

  6. htmlcleaner

    String xpath = "//div"; Object[] myNodes = node.evaluateXPath(xpath); for (Object obj : my ...

  7. 菜鸟聊:PHP

    学习PHP已经有2个月时间了,从一开始的一片空白,到现在的刚刚入门,我对PHP的了解也有更多的认知,希望通过我对PHP的理解,能帮助到更多像我一样的新手更早的认识PHP.(PS:以下内容的一部分是摘自 ...

  8. wampsever在win10中安装扩展掉坑

    1.必须要退出wampserver 2.php pecl + 3.wampserver 64 3.0.6

  9. Demo学习: ClientInfo

    ClientInfo 获取客户端环境参数,从0.9版本开始新增了TUniClientInfoRec对象,可以得到客户端的一些信息,之前为了获取浏览器版本号需要自己写函数,现在可以直接使用TUniCli ...

  10. Mac技巧之让U盘、移动硬盘在苹果电脑和Windows PC都能识别/读写,且支持4GB大文件:exFAT格式

    如果您的 U 盘.移动硬盘既要用于 PC 又要用于苹果电脑,Mac OS X 系统的 HFS+ 和 Windows 的 NTFS 格式显然都不行……HFS+ 在 Windows 下不识别,NTFS 格 ...