HDU - 2460 Network(桥+LCA)

题目大意:给出一张图,现在要往这张图上加边,问加完边后,这张图还有多少条桥

解题思路:求出连通分量,压缩成点,用桥连接,形成了棵树

每次添加边时,就找一下是否在同一个强连通分量内,如果在同一个强连通分量内,那么桥的数量不变

反之,求出两个点的LCA,并且把LCA到这两个点的桥全部去掉(因为加边后,形成了环,构成了一个新的强连通分量了)

#include <cstdio>
#include <cstring>
using namespace std;
#pragma comment(linker,"/STACk:10240000,10240000")
#define N 100010
#define M 400010
#define min(a, b) ((a) < (b) ? (a) : (b))

struct Edge{
    int to, next;
}E[M];

int n, m, tot, dfs_clock, bnum;
int head[N], f[N], low[N], pre[N];
bool isbridge[N], mark[N];

void AddEdge(int u, int v) {
    E[tot].to = v; E[tot].next = head[u]; head[u] = tot++;
    u = u ^ v; v = u ^ v; u = u ^ v;
    E[tot].to = v; E[tot].next = head[u]; head[u] = tot++;
}

void init() {
    memset(head, -1, sizeof(head));
    tot = 0;

    int u, v;
    for (int i = 0; i < m; i++) {
        scanf("%d%d", &u, &v);
        AddEdge(u, v);
    }
}

void dfs(int u, int fa) {
    low[u] = pre[u] = ++dfs_clock;
    bool flag = false;

    for (int i = head[u]; i != -1; i = E[i].next) {
        int v = E[i].to;
        if (v == fa && !flag) {
            flag = true;
            continue;
        }

        if (!pre[v]) {
            f[v] = u;
            dfs(v, u);
            low[u] = min(low[u], low[v]);
            if (low[v] > pre[u]) {
                isbridge[v] = 1;
                bnum++;
            }
        }
        else if (pre[v] <  pre[u]) {
            low[u] = min(low[u], pre[v]);
        }
    }
}

void LCA(int u, int v) {
    while (pre[u] > pre[v]) {
        if (isbridge[u]) {
            bnum--;
            isbridge[u] = 0;
        }
        u = f[u];
    }

    while (pre[u] < pre[v]) {
        if (isbridge[v]) {
            bnum--;
            isbridge[v] = 0;
        }
        v = f[v];
    }

    while (u != v) {
        while (pre[u] > pre[v]) {
            if (isbridge[u]) {
                bnum--;
                isbridge[u] = 0;
            }
            u = f[u];
        }
    }
}

int cas = 1;
void solve() {
    memset(pre, 0, sizeof(pre));
    memset(isbridge, 0, sizeof(isbridge));
    dfs_clock = bnum = 0;
    for (int i = 1; i <= n; i++)
        f[i] = i;
    dfs(1, -1);
    int q, u, v;
    scanf("%d", &q);
    printf("Case %d:\n", cas++);
    while (q--) {
        scanf("%d%d", &u, &v);
        LCA(u, v);
        printf("%d\n", bnum);
    }
    printf("\n");
}

int main() {
    while (scanf("%d%d", &n, &m) != EOF && n + m) {
        init();
        solve();
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-12-23 07:46:08

HDU - 2460 Network(桥+LCA)的相关文章

HDU 2460 Network(双连通+树链剖分+线段树)

HDU 2460 Network 题目链接 题意:给定一个无向图,问每次增加一条边,问个图中还剩多少桥 思路:先双连通缩点,然后形成一棵树,每次增加一条边,相当于询问这两点路径上有多少条边,这个用树链剖分+线段树处理 代码: #include <cstdio> #include <cstring> #include <algorithm> #include <vector> using namespace std; #pragma comment(linke

HDU 2460 Network(桥+LCA)

http://acm.hdu.edu.cn/showproblem.php?pid=2460 题意:给出图,求每次增加一条边后图中桥的数量. 思路: 先用tarjan算法找出图中所有的桥,如果lowv>pre[u],那么u—v就是桥,此时可以标记一下v. 之后就是利用LCA,找到两个节点的公共祖先,在这条路径上的桥就不再是桥了.(此时就相当于这些桥组成的树,可以在脑海中缩点) 1 #include<iostream> 2 #include<algorithm> 3 #incl

hdu 2460 Network (双连通分支+暴力LCA)

题意:在一张图中给出q个加边操作,问你每次操作之后图中割边的个数.点数1e5询问1000 思路:这道题的做法是先对图进行缩点,然后变成一颗树,每次添加新边若是边的两个端点属于不同的分支则一定会形成一个环,这时暴力lca标记所有换上的边有割边变为不是割边.每次统计就可以了.理论上说,每次给V字形的图复杂度会是1e8还有多组数据可能会超时,但这道题能通过.另外这道题会爆栈,注意c++扩栈. 代码如下: 1 /**********************************************

HDU 2460 Network 傻逼Tarjan

Network Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1014    Accepted Submission(s): 206 Problem Description A network administrator manages a large network. The network consists of N comput

HDU 4822 Tri-war(LCA树上倍增)(2013 Asia Regional Changchun)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4822 Problem Description Three countries, Red, Yellow, and Blue are in war. The map of battlefield is a tree, which means that there are N nodes and (N – 1) edges that connect all the nodes. Each country

Caocao&#39;s Bridges HDU - 4738 找桥

题意: 曹操在赤壁之战中被诸葛亮和周瑜打败.但他不会放弃.曹操的军队还是不擅长打水仗,所以他想出了另一个主意.他在长江上建造了许多岛屿,在这些岛屿的基础上,曹操的军队可以轻易地攻击周瑜的军队.曹操还修建了连接岛屿的桥梁.如果所有的岛屿都用桥连接起来,曹操的军队就可以很方便地部署在这些岛屿之间.周瑜无法忍受,他想毁掉曹操的一些桥梁,把一个或多个岛屿与其他岛屿分开.周瑜身上只有一颗炸弹,是诸葛亮留下的,所以他只能毁掉一座桥.周瑜必须派人带着炸弹去炸毁那座桥.桥上可能有警卫.轰炸队的士兵人数不能少于一

HDU 3078:Network(LCA之tarjan)

http://acm.hdu.edu.cn/showproblem.php?pid=3078 题意:给出n个点n-1条边m个询问,每个点有个权值,询问中有k,u,v,当k = 0的情况是将u的权值修改成v,当k不为0的情况是问u和v的路径中权值第k大的点的权值是多少. 思路:比较暴力的方法,可能数据太水勉强混过去了.对于每一个询问的时候保留两个点之间的lca,还有计算出两个点之间的点的个数(询问的时候如果点的个数小于k就不用算了),然后tarjan算完之后对每个询问再暴力路径上的每个点放进vec

POJ 3694 Network ——(桥 + LCA)

题意:给n个点和m条边,再给出q条边,问每次加一条边以后剩下多少桥. 分析:这题是结合了LCA和dfn的妙用._dfn数组和dfn的意义不一样,并非访问的时间戳,_dfn表示的是被访问的顺序,而且是多线程访问下的顺序,举个例子,同一个点分岔开来的点,距离这个点相同距离的点,他们的_dfn的值是相同的,而dfn不是,类似于单线程dfs访问的各点的dfn值是不同的. 具体见代码: 1 #include <stdio.h> 2 #include <algorithm> 3 #includ

HDU 3078 Network LCA水题

Problem Description The ALPC company is now working on his own network system, which is connecting all N ALPC department. To economize on spending, the backbone network has only one router for each department, and N-1 optical fiber in total to connec