题目大意:
给你一个无向图,问加一条边之后最少还剩下几座桥。
(注意重边处理)
 
分析:其实当我们把边双连通分量给求出来之后我们就能将连通块求出来,这样我们就可以重新构图。重新构造出来的图肯定是一颗树了,
那么问题就转化为求树的哪两个节点的距离最长。我们可以随便找一个点S开始BFS, BFS到这个点最远的那个点P,然后再从这个最远点P开始BFS,BFS到P最远的点E,  PE之间的距离就是这个图上最大的距离。
 
注:此题需要手动扩栈
#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <queue>
#include <cmath>
#include <stack>
#include <cstring>
usingnamespace std;
#define INF 0xfffffff
#define maxn 200005
#define min(a,b) (a<b?a:b)
int m, n, Time, top, cnt;
int blocks[maxn], dfn[maxn], low[maxn], Stacks[maxn], Father[maxn];
int step[maxn];
vector<vector<int> > G;
vector<vector<int> > G2;
void init()
{
memset(dfn, , sizeof(dfn));
memset(low, , sizeof(low));
memset(blocks, , sizeof(blocks));
Time = top = cnt = ;
G.clear();
G.resize(n+); G2.clear();
G2.resize(n+);
}
void Tarjan(int u,int fa)
{
dfn[u] = low[u] = ++Time;
Stacks[top ++] = u;
Father[u] = fa;
int len = G[u].size(), k = , v; for(int i=; i<len; i++)
{
v = G[u][i]; if( !k && fa == v)
{
k ++;
continue;
} if( !low[v] )
{
Tarjan(v, u);
low[u] = min(low[u], low[v]);
}
else
low[u] = min(low[u], dfn[v]);
} if(dfn[u] == low[u])
{
do
{
v = Stacks[--top];
blocks[v] = cnt;
}while(u != v);
cnt ++;
}
}
int BFS(int s,int flag)
{
int P, Pn;
queue<int> Q;
Q.push(s);
memset(step, -, sizeof(step));
step[s] = ;
while( Q.size() )
{
P = Q.front();
Q.pop(); int len = G2[P].size(); for(int i=; i<len; i++)
{
Pn = G2[P][i]; if( step[Pn] == -)
{
step[Pn] = step[P] + ;
Q.push(Pn);
}
}
} if(flag == )
return P;
return step[P];
}
void solve()
{
int ans = , i;
for(i=; i<=n; i++)
{
if(!low[i])
Tarjan(i, i);
} for(i=; i<=n; i++)
{
int v = Father[i]; if(blocks[i] != blocks[v])
{ /**重新构图*/
G2[blocks[i] ].push_back(blocks[v]);
G2[blocks[v] ].push_back(blocks[i]);
}
} int p = BFS(,);///以0为起点经行一次BFS返回最远距离的编号 ans = cnt - BFS(p, ) - ;///返回最远距离的长度
printf("%d\n", ans); } int main()
{
while(scanf("%d %d",&n, &m), m+n)
{
init();
while(m--)
{
int a, b;
scanf("%d %d",&a, &b);
G[a].push_back(b);
G[b].push_back(a);
}
solve();
}
return0;
}
/*
5 4
1 2
1 3
1 4
2 5
*/

HDU 4612 Warm up(手动扩栈,求树上哪两个点的距离最远)的更多相关文章

  1. HDU 4612 Warm up tarjan缩环+求最长链

    Warm up Problem Description   N planets are connected by M bidirectional channels that allow instant ...

  2. HDU 4612 Warm up —— (缩点 + 求树的直径)

    题意:一个无向图,问建立一条新边以后桥的最小数量. 分析:缩点以后,找出新图的树的直径,将这两点连接即可. 但是题目有个note:两点之间可能有重边!而用普通的vector保存边的话,用v!=fa的话 ...

  3. Hdu 4612 Warm up (双连通分支+树的直径)

    题目链接: Hdu 4612 Warm up 题目描述: 给一个无向连通图,问加上一条边后,桥的数目最少会有几个? 解题思路: 题目描述很清楚,题目也很裸,就是一眼看穿怎么做的,先求出来双连通分量,然 ...

  4. hdu 4612 Warm up 双连通+树形dp思想

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

  5. HDU 4612 Warm up(2013多校2 1002 双连通分量)

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

  6. HDU 4612——Warm up——————【边双连通分量、树的直径】

    Warm up Time Limit:5000MS     Memory Limit:65535KB     64bit IO Format:%I64d & %I64u Submit Stat ...

  7. hdu 4612 Warm up(无向图Tarjan+树的直径)

    题意:有N个点,M条边(有重边)的无向图,这样图中会可能有桥,问加一条边后,使桥最少,求该桥树. 思路:这个标准想法很好想到,缩点后,求出图中的桥的个数,然后重建图必为树,求出树的最长直径,在该直径的 ...

  8. HDU 4612 Warm up(Tarjan)

    果断对Tarjan不熟啊,Tarjan后缩点,求树上的最长路,注意重边的处理,借鉴宝哥的做法,开标记数组,标记自己的反向边. #pragma comment(linker, "/STACK: ...

  9. HDU 4612 Warm up(双连通分量缩点+求树的直径)

    思路:强连通分量缩点,建立一颗新的树,然后求树的最长直径,然后加上一条边能够去掉的桥数,就是直径的长度. 树的直径长度的求法:两次bfs可以求,第一次随便找一个点u,然后进行bfs搜到的最后一个点v, ...

随机推荐

  1. nodejs 按行读取 readline

                fs.mkdirSync('./yotmp');      }                  log(out);               input: file,    ...

  2. ASP.NET中如何生成图形验证码

    通常生成一个图形验证码主要 有3个步骤: (1)随机产生一个长度为N的随机字符串,N的值可由开发可由开发人员自行设置.该字符串可以包含数字.字母等. (2)将随机生成的字符串创建成图片,并显示. (3 ...

  3. hibernate通过判断参数动态组合Hql语句,生成基本通用查询

    // public List find(Station entity) { List reuslt = null; // 字符串辅助类 StringBuffer hql = new StringBuf ...

  4. VS2015 Cordova Ionic移动开发(二)

    一.创建空白Cordova应用 打开VS,选择[新建项目],选择其它语言JavaScript或者TypeScript,语言的话就按个人喜好,喜欢JS就用JS,喜欢TS就用TS,推荐使用TS书写,代码结 ...

  5. Asp.Net 注册 邮箱激活

    数据库 表的设计 State为用户状态  0为禁用  1为可用  默认为0,下面有个UserGUID,这个字段将来用于激活账户 首先你要写一个表单,验证码神马的,这个我就不写了..直接写处理的 代码在 ...

  6. 【BZOJ3673】【可持久化并查集】可持久化并查集 by zky

    Description n个集合 m个操作操作:1 a b 合并a,b所在集合2 k 回到第k次操作之后的状态(查询算作操作)3 a b 询问a,b是否属于同一集合,是则输出1否则输出0 0<n ...

  7. php中文乱码

    一.         首先是PHP网页的编码 1.     php文件本身的编码与网页的编码应匹配 a.     如果欲使用gb2312编码,那么php要输出头:header(“Content-Typ ...

  8. 【实习记】2014-08-10(上)代码跟踪git的想法+归并排序的debug过程

        (冒泡,选择,插入,希尔,快速,归并,堆排)周末加班学习C++,打算用C++写七大经典排序代码.发现3个月前自己写的七大经典排序代码(C Language)突然运行出错. Makefile内容 ...

  9. Java笔记原生数据类型【二】

    1.Java中的数据类型分为: 1)原生类型(primitive Data type) 2.)引用类型(对象类型) (Reference Type) 1.变量和常量: 常量: 就是值不会变化的量: 变 ...

  10. TatukGIS - GisDefs - ColorToHSL 过程

    过程名称  ColorToHSL 所在单元  GisDefs 过程原型           procedure ColorToHSL(const _color: TColor; var _h: Rea ...