POJ 3694 强连通分量+LCA

来源:互联网 发布:达梦数据库驱动下载 编辑:程序博客网 时间:2024/05/16 12:30

点击打开链接

题意:给一个图,然后依次加进去边,问每次加过边后还有几个桥,之前加入的会影响后面加入的

思路:先将图的桥全部找出来,然后将桥的点标记上,然后不需要缩点,直接进行裸的LCA,再找最近公共祖先的时候,遇到标记的点将结果减1,然后将标记取消,不知道为什么我写的跑的特别慢,别人写的都很快,有神犇知道求指教

#include <vector>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <iostream>#include <algorithm>using namespace std;typedef long long ll;const int inf=0x3f3f3f3f;const int maxn=100010;vector<int>G[maxn];vector<int>GG[maxn];int L[maxn],vis[maxn],E[maxn],stack1[maxn];int depth[maxn],par[maxn];int vis1[maxn];int n,m,k,kk,cnt;void dfs(int x,int fa){    vis[x]=1;L[x]=k;E[x]=k++;    int flag=0;    for(unsigned int i=0;i<G[x].size();i++){        int t=G[x][i];        if(t!=fa){            if(!vis[t]){                dfs(t,x);                par[t]=x;                L[x]=min(L[x],L[t]);                if(L[t]>E[x]){                    cnt++;vis1[t]=1;                }            }else L[x]=min(L[x],E[t]);        }else{            if(flag) L[x]=min(L[x],E[t]);            flag++;        }    }    if(L[x]==E[x]){        while(stack1[kk]!=x&&kk>0){            L[stack1[kk-1]]=L[x];            kk--;            vis[stack1[kk]]=0;        }    }}void tarjan(){    kk=0;k=1;dfs(1,1);}int LCA(int u,int v){    int sum=0;    while(E[u]>E[v]){        if(vis1[u]==1){            sum++;vis1[u]=0;        }        u=par[u];    }    while(E[v]>E[u]){        if(vis1[v]==1){            sum++;vis1[v]=0;        }        v=par[v];    }    while(u!=v){        if(vis1[u]==1){            sum++;vis1[u]=0;        }        if(vis1[v]==1){            sum++;vis1[v]=0;        }        u=par[u];v=par[v];    }    return sum;}int main(){    int a,b,t=1,q;    while(scanf("%d%d",&n,&m)!=-1){        if(n==0&&m==0) break;        for(int i=0;i<maxn;i++){            G[i].clear();GG[i].clear();        }        memset(vis,0,sizeof(vis));        memset(vis1,0,sizeof(vis1));        for(int i=0;i<m;i++){            scanf("%d%d",&a,&b);            G[a].push_back(b);            G[b].push_back(a);        }        cnt=0;tarjan();//        for(int i=1;i<=n;i++) cout<<E[i]<<" ";cout<<endl;//        for(int i=1;i<=n;i++) cout<<vis1[i]<<" ";cout<<endl;        scanf("%d",&q);        printf("Case %d:\n",t++);        while(q--){            scanf("%d%d",&a,&b);            if(cnt==0){                printf("%d\n",cnt);                continue;            }            int ans=LCA(a,b);            cnt-=ans;            printf("%d\n",cnt);        }        printf("\n");    }    return 0;}


 

0 0
原创粉丝点击