POJ3694-Network(Tarjan缩点+LCA)

题目链接

题意:给你一个连通图。然后再给你n个询问,每一个询问给一个点u,v表示加上u,v之后又多少个桥。

思路:用Tarjan缩点后,形成一棵树,所以树边都是桥了。然后增加边以后,查询LCA,LCA上的桥都减掉。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <utility>
#include <algorithm>

using namespace std;

const int MAXN = 100005;

struct Edge{
    int to, next;
}edge[MAXN * 5];
int head[MAXN], tot;
int Low[MAXN], DFN[MAXN];
int Index, top;
int bridge;
int n, m;
int f[MAXN], ancestor[MAXN];

int find(int x) {
    return x == f[x] ? x : f[x] = find(f[x]);
}

bool Union(int a, int b) {
    int pa = find(a);
    int pb = find(b);
    if (pa != pb) {
        f[pa] = pb;
        return true;
    }
    return false;
}

void addedge(int u, int v) {
    edge[tot].to = v;
    edge[tot].next = head[u];
    head[u] = tot++;
}

void Tarjan(int u, int pre) {
    int v;
    Low[u] = DFN[u] = ++Index;
    for (int i = head[u]; i != -1; i = edge[i].next) {
        v = edge[i].to;
        if (v == pre) continue;
        if (!DFN[v]) {
            Tarjan(v, u);
            ancestor[v] = u;
            if (Low[u] > Low[v]) Low[u] = Low[v];
            if (Low[v] > DFN[u])
                bridge++;
            else
                Union(u, v);
        }
        else if (Low[u] > DFN[v])
            Low[u] = DFN[v];
    }
}

void init() {
    memset(head, -1, sizeof(head));
    memset(DFN, 0, sizeof(DFN));
    tot = 0;
    Index = top = 0;
    bridge = 0;
    memset(ancestor, 0, sizeof(ancestor));
    for (int i = 1; i <= n; i++)
        f[i] = i;
}

void solve() {
    for (int i = 1; i <= n; i++)
        if (!DFN[i])
            Tarjan(i, -1);
}

void lca(int u, int v) {
    while (u != v) {
        while (DFN[u] >= DFN[v] && u != v) {
            if (Union(u, ancestor[u]))
                bridge--;
            u = ancestor[u];
        }
        while (DFN[v] >= DFN[u] && u != v) {
            if (Union(v, ancestor[v]))
                bridge--;
            v = ancestor[v];
        }
    }
}

int main() {
    int t = 1;
    while (scanf("%d%d", &n, &m)) {
        if (n == 0 && m == 0) break;
        init();
        int u, v;
        for (int i = 0; i < m; i++) {
            scanf("%d%d", &u, &v);
            addedge(u, v);
            addedge(v, u);
        }
        solve();

        printf("Case %d:\n", t++);
        int k;
        scanf("%d", &k);
        while (k--) {
            scanf("%d%d", &u, &v);
            lca(u, v);
            printf("%d\n", bridge);
        }
        printf("\n");
    }
    return 0;
}
时间: 2024-08-29 01:30:56

POJ3694-Network(Tarjan缩点+LCA)的相关文章

poj3694(强连通缩点+lca)

传送门:Network 题意:给你一个连通图,然后再给你n个询问,每个询问给一个点u,v表示加上u,v之后又多少个桥. 分析:方法(1219ms):用并查集缩点,把不是桥的点缩成一个点,然后全图都是桥,每次加边的两个点如果是缩后的同个点,必定不是桥,否则是桥,再把它们到达lca之间的点缩成一点. 方法2(A巨思路360ms):先一次tarjan缩点,重新建图得到一颗树,每次加边,两个端点到它们的lca之间的边都不再是桥,所以每一次我们都可以通过暴力求出lca,然后统计出少了多少条桥,但是暴力统计

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

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

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

【连通图|边双连通分量+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

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

POJ 1236 Network of Schools(强连通 Tarjan+缩点)

POJ 1236 Network of Schools(强连通 Tarjan+缩点) ACM 题目地址:POJ 1236 题意: 给定一张有向图,问最少选择几个点能遍历全图,以及最少加入?几条边使得有向图成为一个强连通图. 分析: 跟HDU 2767 Proving Equivalences(题解)一样的题目,只是多了个问题,事实上转化成DAG后就不难考虑了,事实上仅仅要选择入度为0的点即可了. 代码: /* * Author: illuz <iilluzen[at]gmail.com> *

P2746 [USACO5.3]校园网Network of Schools tarjan 缩点

题意 给出一个有向图,A任务:求最少需要从几个点送入信息,使得信息可以通过有向图走遍每一个点B任务:求最少需要加入几条边,使得有向图是一个强联通分量 思路 任务A,比较好想,可以通过tarjan缩点,求出入度为0的点的个数任务B一开始以为任务A,B没有关系其实是入度为0的点的个数.出度为0的点的个数的最大值.因为任务B要求在任意学校投放软件使得所有学校都能收到,所以很明显是需要整张图形成一个环,而环中所有节点入度和出度都不为0,所以需要把所有入度和出度的点度数增加. (注意判断本身就全联通的情况

tarjan+缩点+强连通定理

C - Network of Schools Time Limit:1000MS     Memory Limit:10000KB     64bit IO Format:%I64d & %I64u Submit Status Description A number of schools are connected to a computer network. Agreements have been developed among those schools: each school mai

【BZOJ-1924】所驼门王的宝藏 Tarjan缩点(+拓扑排序) + 拓扑图DP

1924: [Sdoi2010]所驼门王的宝藏 Time Limit: 5 Sec  Memory Limit: 128 MBSubmit: 787  Solved: 318[Submit][Status][Discuss] Description Input 第一行给出三个正整数 N, R, C. 以下 N 行,每行给出一扇传送门的信息,包含三个正整数xi, yi, Ti,表示该传送门设在位于第 xi行第yi列的藏宝宫室,类型为 Ti.Ti是一个1~3间的整数, 1表示可以传送到第 xi行任意