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:\n", icase++);
        while(Q--)
        {
            scanf("%d %d", &a, &b);
            LCA(a, b);
            printf("%d\n", bridge_num);
        }
    }
    return 0;
}
时间: 2024-10-04 13:42:06

POJ3694 Network(连通图+LCA)的相关文章

POJ3694 Network 割边+LCA

题目链接: Poj3694 题意: 给出一个N(1 ≤ N ≤ 100,000)个点 和 M(N - 1 ≤ M ≤ 200,000)的连通图. 有Q ( 1 ≤ Q ≤ 1,000)个询问 每次询问增加一条边(累加下去) 输出每增加一条边后剩下的桥的数量 题解: 10W点加1000次询问 每次询问都用Tarjin算法求一次肯定会超时的 考虑  每次加一条边a-b的实质: 从a到b的路径中的所有割边都将消失 那如何记录这条路径呢 在Tarjan算法递归的过程中通过树边建立一棵树 然后每次询问分别

[POJ3694]Network(LCA, 割边, 桥)

题目链接:http://poj.org/problem?id=3694 题意:给一张图,每次加一条边,问割边数量. tarjan先找出所有割边,并且记录每个点的父亲和来自于哪一条边,然后询问的时候从两个点向上找lca,沿途更新割边数量和割边状态即可. AC代码 1 /* 2 ━━━━━┒ギリギリ♂ eye! 3 ┓┏┓┏┓┃キリキリ♂ mind! 4 ┛┗┛┗┛┃\○/ 5 ┓┏┓┏┓┃ / 6 ┛┗┛┗┛┃ノ) 7 ┓┏┓┏┓┃ 8 ┛┗┛┗┛┃ 9 ┓┏┓┏┓┃ 10 ┛┗┛┗┛┃ 11 ┓

hdu2460&amp;&amp;poj3694 缩点+lca变形

http://acm.hdu.edu.cn/showproblem.php?pid=2460 http://poj.org/problem?id=3694 Problem Description A network administrator manages a large network. The network consists of N computers and M links between pairs of computers. Any pair of computers are c

【连通图|边双连通分量+Tarjan+并查集】POJ-3694 Network(400+ms)

Network Time Limit: 5000MS Memory Limit: 65536K Description A network administrator manages a large network. The network consists of N computers and M links between pairs of computers. Any pair of computers are connected directly or indirectly by suc

Poj 3694 Network (连通图缩点+LCA+并查集)

题目链接: Poj 3694 Network 题目描述: 给出一个无向连通图,加入一系列边指定的后,问还剩下多少个桥? 解题思路: 先求出图的双连通分支,然后缩点重新建图,加入一个指定的边后,求出这条边两个端点根节点的LCA,统计其中的桥,然后把这个环中的节点加到一个集合中,根节点标记为LCA. 题目不难,坑在了数组初始化和大小 1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #inclu

POJ3694 Network(Tarjan双联通分图 LCA 桥)

链接:http://poj.org/problem?id=3694 题意:给定一个有向连通图,每次增加一条边,求剩下的桥的数量. 思路: 给定一个无向连通图,添加一条u->v的边,求此边对图剩余的桥的数量的影响:     若u,v在同一个强联通分量中,则是否添加无影响.否则从u,v的LCA到u,v的边上所有的桥都不再是桥.     在Tarjan算法中,对在同一个强联通分量中的点使用并查集合并,实现缩点,同时记录父亲节点.若u,v属于不同的强连通分量,将dfn较大的点(设为v)向上合并直到dfn

poj3694 network(边双联通分量+lca+并查集)

题    目    传    送    们    在    这 题目大意 有一个由n个点和m条边组成的无向联通图. 现在有Q个操作,每次操作可以在点x,y之间连一条边. 问你每次操作后有多少个多少个桥(即删掉后就会使图不联通的边). 解题思路 根据边双联通的定义,我们知道将边双联通分量缩点后的图,其中的边即为桥. 我们将这个图缩点,就变成了一棵树. 而每次在两个不同的边双联通分量x,y之间加边后,就出现了一个包含x,y的环,其中原先这颗树上x,y的树上最短路径就不在是边. 所以对于每个x,y,我

POJ3694(KB9-D 割边+LCA)

Network Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 10371   Accepted: 3853 Description A network administrator manages a large network. The network consists of N computers and M links between pairs of computers. Any pair of computers

Codeforces 690 C3. Brain Network (hard) LCA

C3. Brain Network (hard) Breaking news from zombie neurology! It turns out that – contrary to previous beliefs – every zombie is born with a single brain, and only later it evolves into a complicated brain structure. In fact, whenever a zombie consum