Warm up HDU - 4612( 树的直径 边双连通分量)
Posted wtsruvf
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Warm up HDU - 4612( 树的直径 边双连通分量)相关的知识,希望对你有一定的参考价值。
求在图中新建一条边后 剩下的最少的桥的数量。。
先tarjan求桥的数量。。然后缩点。。以连通分量为点建图 bfs求直径
最后用桥的数量减去直径即为答案
bfs求直径
https://www.cnblogs.com/WTSRUVF/p/9307517.html
#include <iostream> #include <cstdio> #include <cstring> #include <queue> #include <algorithm> #include <vector> #include <stack> #define mem(a, b) memset(a, b, sizeof(a)) using namespace std; const int maxn = 200010, INF = 0x7fffffff; int pre[maxn], low[maxn], sccno[maxn], d[maxn], head[maxn], vis[maxn*10]; int dfs_clock, n, m, scc_cnt, bridge, maxway, pos; stack<int> S; int cnt1, cnt2; struct edge { int u, v, next; }Edge1[maxn*10],Edge2[maxn*10]; void add1(int u, int v) { Edge1[cnt1].u = u; Edge1[cnt1].v = v; Edge1[cnt1].next = head[u]; head[u] = cnt1++; } void add2(int u, int v) { Edge2[cnt2].u = u; Edge2[cnt2].v = v; Edge2[cnt2].next = head[u]; head[u] = cnt2++; } void init() { dfs_clock = 0; scc_cnt = 0; cnt1 = cnt2 = 0; bridge = 0; mem(pre, 0); mem(vis, 0); mem(low, 0); mem(head, -1); mem(sccno, 0); } void tarjan(int u) { pre[u] = low[u] = ++dfs_clock; S.push(u); for(int i=head[u]; i != -1; i=Edge1[i].next) { int v = Edge1[i].v; if(vis[i]) continue; vis[i] = vis[i^1] = 1; // 标记同向边和反向边 if(!pre[v]) { tarjan(v); low[u] = min(low[v], low[u]); } else if(!sccno[v]) low[u] = min(low[u], pre[v]); } if(low[u] == pre[u]) { scc_cnt++; for(;;) { int x = S.top(); S.pop(); sccno[x] = scc_cnt; if(x == u) break; } } } void bfs(int u) { queue<int> Q; mem(d, 0); mem(vis, 0); Q.push(u); d[u] = 0; vis[u] = 1; maxway = 0, pos = u; while(!Q.empty()) { u = Q.front(); Q.pop(); for(int i=head[u]; i != -1; i=Edge2[i].next) { int v = Edge2[i].v; if(vis[v]) continue; vis[v] = 1; d[v] = d[u] + 1; if(d[v] > maxway) maxway = d[v], pos = v; Q.push(v); } } } int main() { while(~scanf("%d%d",&n, &m) && n+m) { init(); for(int i=0; i<m; i++) { int u, v; scanf("%d%d",&u, &v); add1(u, v); add1(v, u); } tarjan(1); mem(head, -1); for(int i=0;i < cnt1; i+=2) //以连通分量建图 顺便求桥的数量 if(sccno[Edge1[i].u] != sccno[Edge1[i].v]) { add2(sccno[Edge1[i].u], sccno[Edge1[i].v]); add2(sccno[Edge1[i].v], sccno[Edge1[i].u]); bridge++; } bfs(sccno[1]); bfs(pos); printf("%d ",bridge - maxway); } return 0; }
以上是关于Warm up HDU - 4612( 树的直径 边双连通分量)的主要内容,如果未能解决你的问题,请参考以下文章
HDU 4612 Warm up(双连通分量缩点+求树的直径)