Network POJ - 3694(lca并查集+连通图求桥)

就是求出原先图中的桥的数量,在每一次询问时加入一条新边,求加入当前边后图中剩余的桥的数量

求出原先图中的桥的数量,然后减去新加入边的两端点之间的桥的数量,就是剩余桥的数量。。

用并查集把属于同一集合的放到一起(即两个点之间没有桥的)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
#include <algorithm>
#include <vector>
#define mem(a, b) memset(a, b, sizeof(a))
using namespace std;
const int maxn = 400100, INF = 0x7fffffff;
int pre[maxn], f[maxn], pa[maxn];
int dfs_clock;
int n, m, ret;
vector<int> G[maxn];
int find(int x)
{
    return f[x]==x?x:(f[x]=find(f[x]));
}

int Union(int u, int v)
{
    int r = find(u);
    int l = find(v);
    if(r == l) return 0;
    f[r] = l;
    return 1;
}

int dfs(int u, int fa)
{
    pa[u] = fa;
    int lowu = pre[u] = ++dfs_clock;
    for(int i=0; i<G[u].size(); i++)
    {
        int v = G[u][i];
        if(!pre[v])
        {
     //       pa[v] = u;
            int lowv = dfs(v, u);
            lowu = min(lowu, lowv);
            if(lowv > pre[u])
                ret++;
            else
                Union(u, v);   //如果u和v之间没桥,那么u和v就同属于一个集合
        }
        else if(pre[v] < pre[u] && v != fa)
            lowu = min(lowu, pre[v]);
    }

    return lowu;
}

int lca(int u, int v)
{
    int r = find(u);
    int l = find(v);
    if(r == l)
        return ret;
    if(pre[u] > pre[v])
        swap(u, v);
    while(pre[u] < pre[v])
    {
        if(Union(pa[v], v))
            ret--;
        v = pa[v];
    }
    while(u != v)     //v经过上一个while后要么是u 要么是u和v的最近公共祖先
    {
        if(Union(u, pa[u]))
            ret--;
        u = pa[u];
    }
    return ret;
}

void init()
{
    mem(pre, 0);
    mem(pa, 0);
    for(int i=0; i<=n; i++) f[i] = i;
    dfs_clock = 0;
    ret = 0;
}

int main()
{
    int kase = 0;
    while(cin>> n >> m && n+m)
    {
        init();
        for(int i=0; i<m; i++)
        {
            int u, v;
            cin>> u >> v;
            G[u].push_back(v);
            G[v].push_back(u);
        }
        dfs(1, -1);
        int Q;
        cin>> Q;
        printf("Case %d:\n",++kase);
        for(int i=0; i<Q; i++)
        {
            int u, v;
            cin>> u >> v;
            cout<< lca(u, v) <<endl;
        }

    }

    return 0;
}

原文地址:https://www.cnblogs.com/WTSRUVF/p/9302594.html

时间: 2024-10-07 20:04:15

Network POJ - 3694(lca并查集+连通图求桥)的相关文章

【CodeForces】827 D. Best Edge Weight 最小生成树+倍增LCA+并查集

[题意]给定n个点m条边的带边权无向连通图,对每条边求最大边权,满足其他边权不变的前提下图的任意最小生成树都经过它.n,m<=2*10^5,1<=wi<=10^9. [算法]最小生成树+倍增LCA+并查集 [题解]首先求出图的一个最小生成树,则所有边分成树边和非树边. 对于非树边(u,v),假设u和v在最小生成树上的路径的最大边权Max,那么一定满足w(u,v)<=Max /////////////////////////////////////// 原文地址:https://ww

POJ 2492 (简单并查集) A Bug&#39;s Life

题意:有编号为1~n的虫子,开始假设这种昆虫是异性恋.然后已知xi 和 yi进行交配,根据已知情况分析能否推理出其中是否有同性恋 这道题和 POJ 1182 食物链 十分相似,不过在更新与父节点关系的时候要简单一些 sex数组保存的是与父节点的性别关系,如果与父节点是同性,则为0,否则是1 每次路径压缩的同时要更新sex[a] = (sex[a] + sex[temp]) % 2; 还有就是如果x 和 y 不在一个集合,两棵树进行合并的时候,考虑x px y py 四者之间的关系,有 paren

Corporative Network(带权并查集)

这个题的题意是  当输入'E'是查找操作,查找从后面这个数到他的父亲这边的值,'I'代表把后面的数作为前面数的父亲 然后他们两个的差值代表这两个边的权值 水水的题 #include <stdio.h> #include <string.h> int par[20005]; int rank1[20005]; int abs(int hh) { return (hh>0)?hh:-hh; } void init() { for(int i=0;i<20005;i++) {

POJ - Colored Sticks - 并查集+字典树

这道题主要还是要判断是不是欧拉图 说白了就是能不能这幅图能不能用一笔画下来,那么就可以知道了,如果是一个环状的,说明奇数度就不存在,否则就只能用两个奇数度(起点终点)//我的理解这是 只需要用字典树将单词变为对应的一个数字,然后并查集操作就可以,需要维护一个度变量 #include<stdio.h> #include<string.h> int du[500010],p[500010]; int tot=1; struct tree { tree *next[30]; int id

poj 2513 欧拉回路+并查集判断是否联通+Trie树

http://poj.org/problem?id=2513 最初看到 第一感觉---map  一看250000的数据量 果断放弃 然后记得以前看过,trie代替map,尤其当数据量特别大的时候 学到了: 1.Trie代替map的思想,可以在单词结尾的tree[i][tk]  这个i作为字符串对应的int值 ,当然这个int值也可以用于建立并查集 2.接上,通过并查集判断,所有的点在同一个集合图就是联通的,否则不联通,注意tree[i][tk]>0 表示是单词结尾, x=Find(x);//这句

UVALive - 3027Corporative Network(带权并查集)

题目: UVALive - 3027Corporative Network(带权并查集) 题目大意:有n和节点,初始时每个节点的父节点都不存在,然后有下面两种操作:I 操作 I a,b 将a的父节点变成b.E操作 E a,查询a到它的父节点的距离. 解题思路:带权并查集.注意这里距离的变化是a -> b,那么a到根节点的距离就是a到b的距离的绝对值 % 1000 + b到它的根节点的距离. 代码: #include <cstdio> #include <cstring> #i

[数论][LCA][并查集]JZOJ 5782 城市猎人

Description 有n个城市,标号为1到n,修建道路花费m天,第i天时,若gcd(a,b)=m-i+1,则标号为a的城市和标号为b的城市会建好一条直接相连的道路,有多次询问,每次询问某两座城市最早什么时候能连通. Input 第一行输入三个正整数n,m,q,其中q表示询问个数.接下来q行,每行两个正整数x,y,表示询问城市x和城市y最早什么时候连通. Output 输出q行,每行一个正整数,表示最早连通的天数 Sample Input Input 1 8 3 3 2 5 3 6 4 8 I

POJ 2524-Ubiquitous Religions(并查集)

Ubiquitous Religions Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 25383   Accepted: 12530 Description There are so many different religions in the world today that it is difficult to keep track of them all. You are interested in findi

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

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