HDU 4612 Warm up(手动扩栈,求树上哪两个点的距离最远)
题目大意:
给你一个无向图,问加一条边之后最少还剩下几座桥。
(注意重边处理)
分析:其实当我们把边双连通分量给求出来之后我们就能将连通块求出来,这样我们就可以重新构图。重新构造出来的图肯定是一颗树了,
那么问题就转化为求树的哪两个节点的距离最长。我们可以随便找一个点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, 0, sizeof(dfn)); memset(low, 0, sizeof(low)); memset(blocks, 0, sizeof(blocks)); Time = top = cnt = 0; G.clear(); G.resize(n+2); G2.clear(); G2.resize(n+2); } void Tarjan(int u,int fa) { dfn[u] = low[u] = ++Time; Stacks[top ++] = u; Father[u] = fa; int len = G[u].size(), k = 0, v; for(int i=0; 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, -1, sizeof(step)); step[s] = 0; while( Q.size() ) { P = Q.front(); Q.pop(); int len = G2[P].size(); for(int i=0; i<len; i++) { Pn = G2[P][i]; if( step[Pn] == -1) { step[Pn] = step[P] + 1; Q.push(Pn); } } } if(flag == 1) return P; return step[P]; } void solve() { int ans = 0, i; for(i=1; i<=n; i++) { if(!low[i]) Tarjan(i, i); } for(i=1; 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,1);///以0为起点经行一次BFS返回最远距离的编号 ans = cnt - BFS(p, 2) - 1;///返回最远距离的长度 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 */