POJ3694 Network(连通图+LCA)

题目链接:http://poj.org/problem?id=3694

题目大意:给定一个图,每次添加一条边(可能有重边)。输出每次添加后桥的

数目。由于添加边的次数比较多,添加一次Tarjin一次明显会超时。后来查到了

LCA算法,利用保存的子节点与最近父节点的关系进行计算的。第一次Tarjin后将

桥和其所在的父子节点关系保存下来,之后的m次添加边只需要在LCA中判断添加

的边是否为桥,若为桥则将此桥标记抹去,并将桥数减一,否则无影响。

附AC代码:

#include <stdio.h>
#include <algorithm>
#include <string.h>
using namespace std;
struct ad
{
    int to, next, used;
}edge[400005];
int head[100005], edge_num, dfn[100005], low[100005], bridge_num, Time, father[100005];
bool isbridge[100005];
void Add(int x, int y)
{
    edge[edge_num].to = y;
    edge[edge_num].next = head[x];
    edge[edge_num].used = 0;
    head[x] = edge_num++;
}
void Init()
{
    memset(head, -1, sizeof(head));
    memset(father, 0, sizeof(father));
    memset(low, 0, sizeof(low));
    memset(dfn, 0, sizeof(dfn));
    memset(isbridge, false, sizeof(isbridge));
    edge_num = Time = bridge_num = 0;
}
void Tarjin(int u, int fa)
{
    father[u] = fa;
    low[u] = dfn[u] = ++Time;
    int i, v;
    for(i=head[u]; i!=-1; i=edge[i].next)
    {
        if(edge[i].used==0)
        {
            edge[i].used = edge[i^1].used = 1;
            v = edge[i].to;
            if(!dfn[v])
            {
                Tarjin(v, u);
                low[u] = min(low[u], low[v]);
                if(low[v]>dfn[u])
                {
                    bridge_num++;
                    isbridge[v] = true;
                }
            }
            else if(v!=fa)
                low[u] = min(low[u], dfn[v]);
        }
    }
}
void LCA(int u, int v)
{
    if(dfn[u]>dfn[v])
        swap(u, v);
    while(dfn[v]>dfn[u])
    {
        if(isbridge[v])bridge_num--;
        isbridge[v] = false;
        v = father[v];
    }

    while(u!=v)
    {
        if(isbridge[u])bridge_num--;
        if(isbridge[v])bridge_num--;
        isbridge[u] = isbridge[v] = false;
        u = father[u];
        v = father[v];
    }
}
int main()
{
    int n, m, icase = 1;
    while(scanf("%d %d", &n, &m), n+m)
    {
        int a, b;
        Init();
        for(int i=1; i<=m; i++)
        {
            scanf("%d %d", &a, &b);
            Add(a, b);
            Add(b, a);
        }
        Tarjin(1, -1);
        int Q;
        scanf("%d", &Q);
        printf("Case %d:
", icase++);
        while(Q--)
        {
            scanf("%d %d", &a, &b);
            LCA(a, b);
            printf("%d
", bridge_num);
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/zznulw/p/5785260.html