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语言(简单游戏)-走出迷宫

    #include <stdio.h> //宏定义 maze[ROWS][COLS];行和列; #define ROWS 7 #define COLS 6 //绘制迷宫(全局变量) char ...

  2. LibCurl笔记四

    1,curl设置fiddler代理curl_easy_setopt(m_easyHandle, CURLOPT_PROXY, "127.0.0.1:8888"); 2,

  3. ZigBee HomeAutomation分析

    引用请注明出处!联系邮箱是huhao0126@163.com 本例程讲解,基于TI CC2530-2.5.1a中的HomeAutomation文件夹中的SampleLight和SampleSwitch ...

  4. C#对象转JSON字符串和JSON字符串转对象

    namespace Net.String.ConsoleApplication { using System; using System.Data; using System.Collections; ...

  5. 让Dock自动 显示/隐藏 不再有延迟

    Safari 5.2 Mac OS X 10.7.2 <ignore_js_op> 可能很多朋友使用Mac的时候都会选择将Dock隐藏(可以在系统偏好设置-Dock中选择),等到使用的时候 ...

  6. centos 7 lNMP 安装之php 篇

    1.准备工作 安装依赖包 yum install -y gcc gcc-c++ autoconf libjpeg libjpeg-devel libpng libpng-devel freetype ...

  7. 记一个JAVA关于日期的坑

    JAVA解析日期格式代码,之前一直写成:“yyyy-MM-dd hh:mm”,比如"2016-01-18 11:00"."2016-01-18 15:00"都可 ...

  8. Python的文件与文件夹操作

    Python的文件与文件夹操作 Python OS模块 1.重命名:os.rename(old, new) 2.删除:os.remove(file) 3.列出目录下的文件 :os.listdir(pa ...

  9. div中加入iframe,可以实现Ajax的功能

    div中加入iframe,可以实现Ajax的功能,如果查询的时候,比如说城市的选择,用Ajax去实现, 在.net 可以考虑用UpdatePanel,但是点击了查询刷新表格(表格需要重新刷新加载,非纯 ...

  10. 约束的DEFERRABLE, NOT DEFERRABLE, INITIALLY IMMEDIATE 和 INITIALLY DEFERRED

    [ CONSTRAINT constraint_name ] { NOT NULL |   NULL |   CHECK ( expression ) [ NO INHERIT ] |   DEFAU ...