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;
}
View Code

 


以上是关于Warm up HDU - 4612( 树的直径 边双连通分量)的主要内容,如果未能解决你的问题,请参考以下文章

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

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

HDU4612 Warm up

HDU 4612 Warm up

hdu4612-Warm up(边的双连通分量)

HDU 4612 Warm upBCC 树的直径