poj 3694 無向圖求橋+lca


題意抽象為:

給一個無向圖和一些詢問

對於每一次詢問:

每次詢問都會在圖上增加一條邊

對於每一次詢問輸出此時圖上橋的個數。

 

橋的定義:刪除該邊后原圖變為多個連通塊。 

 

數據規模:點數N(1 ≤ N ≤ 100,000) ,邊數M(N - 1 ≤ M ≤ 200,000),詢問數Q ( 1 ≤ Q ≤ 1,000)

 

先跑一遍tarjan,對邊雙連通分枝縮一下點。

再維護lca即可。

AC代碼:

#include<cstdio>
#include<cstring>
#include<queue>
#define rep(i,a,b) for(int i=a;i<=b;++i)
using namespace std;
const int MAXV=110000;
const int MAXE=410000;
int DFN[MAXV],low[MAXV],par[MAXV],label[MAXV];
int pointer[MAXV];
int tot,cnt,m,n,Bcnt,ans;
vector<int> graph[MAXV];
struct Edge
{
    int to,next;
    bool vis;
    Edge() {}
    Edge(int b,int nxt,int flag) {to=b,next=nxt,vis=flag;}
}edge[MAXE];
inline void addedge(int a,int b)
{
    edge[tot]=Edge(b,pointer[a],0);
    pointer[a]=tot++;
    edge[tot]=Edge(a,pointer[b],0);
    pointer[b]=tot++;
}
void init()
{
    tot=0;
    cnt=0;Bcnt=0;
    memset(pointer,-1,sizeof(pointer));
    memset(label,0,sizeof(label));
    memset(DFN,0,sizeof(DFN));
}
void tarjan(int u,int pre)
{
    DFN[u]=low[u]=++cnt;
    for(int j=pointer[u];j!=-1;j=edge[j].next)
    {
        int v=edge[j].to;
        if(edge[j].vis) continue;
        edge[j].vis=edge[j^1].vis=1;
        if(!DFN[v])
        {
            par[v]=j;
            tarjan(v,u);
            if(low[v]<low[u]) low[u]=low[v];
        }
        else if(low[u]>DFN[v]) low[u]=DFN[v];
    }
}
void part(int u)
{
    label[u]=Bcnt;
    for(int j=pointer[u];j!=-1;j=edge[j].next)
    {
        int v=edge[j].to;
        if(!label[v]&&edge[j].vis) part(v);
    }
}
int dep[MAXV];
int father[MAXV],a[MAXV];
void lca_bfs(int S)
{
    rep(i,1,Bcnt) dep[i]=-1;
    queue<int>q;
    dep[S]=0;
    q.push(S);
    father[S]=S;
    while(!q.empty())
    {
        int u=q.front();q.pop();
        for(int i=0;i<graph[u].size();++i)
        {
            int v=graph[u][i];
            if(dep[v]==-1)
            {
                dep[v]=dep[u]+1;
                a[v]=1;
                father[v]=u;
                q.push(v);
            }
        }
    }
}
void lca(int u,int v)
{
    if(dep[u]>dep[v]) swap(u,v);
    while(dep[u]<dep[v])
    {
        if(a[v])
        {
            ans--;
            a[v]=0;
        }
        v=father[v];
    }
    while(u!=v)
    {
        if(a[v])
        {
            ans--;
            a[v]=0;
        }
        v=father[v];
        if(a[u])
        {
            ans--;
            a[u]=0;
        }
        u=father[u];
    }
}
int main()
{
   // freopen("in.txt","r",stdin);
    int icase=0;
    while(scanf("%d%d",&n,&m)&&m&&n)
    {
        int a,b;
        init();
        rep(i,1,m)
        {
            scanf("%d%d",&a,&b);
            addedge(a,b);
        }
        tarjan(1,1);
        int tmp,u;
        rep(i,2,n)
        {
            tmp=par[i]^1;
            u=edge[tmp].to;
            if(DFN[u]<low[i])
            {
                edge[tmp].vis=edge[tmp^1].vis=0;
            }
        }
        rep(i,1,n)
        {
            if(!label[i])
            {
                Bcnt++;
                part(i);
            }
        }
        ans=Bcnt-1;
        rep(i,2,n)
        {
            if(!edge[par[i]].vis)
            {
                tmp=par[i]^1;
                u=edge[tmp].to;
                graph[label[u]].push_back(label[i]);
                graph[label[i]].push_back(label[u]);
            }
        }
        lca_bfs(1);
        int v,q;
        scanf("%d",&q);
        printf("Case %d:\n",++icase);
        rep(i,1,q)
        {
            scanf("%d%d",&u,&v);
            lca(label[u],label[v]);
            printf("%d\n",ans);
        }
        printf("\n");

    }
    return 0;
}

 


注意!

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



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