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;
}

 


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
  © 2014-2022 ITdaan.com 联系我们: