Network POJ - 3694 无向图找桥

题意:

给你一个无向图,你需要找出来其中有几个桥

桥:
1、存在重边必定不为桥
2、low[v]>dfn[u]

代码:

//题意很清晰
//就是这个需要先找出来原无向图中的桥个数,然后在判断添加边之后会不会形成环,形成环的话,这个环里面的是没有桥的
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<map>
#include<math.h>
#include<set>
#include<queue>
using namespace std;
typedef long long ll;
const int maxn=100005;
const int mod=26;
const int INF=0x3f3f3f3f;
const int block=300;
int dfn[maxn],low[maxn],isbridge[maxn],visit[maxn],depth;
int pre[maxn],bridge_cnt;
vector<int>w[maxn];
void dfs(int u,int fu)  //这是无向图找桥的方法,当无环图出现环的时候,那么这个里面没有桥,其他情况有
{   //有向图找桥的时候,当出现一个环的时候这个环里面的边也都不是桥,相当于把这个环缩成了一个超级点
    dfn[u]=low[u]=++depth;
    visit[u]=1;
    int flag=1;
    int len=w[u].size();
    for(int i=0;i<len;++i)
    {
        int v=w[u][i];
        //printf("%d %d**1**\n",u,v);
        if(flag && v==fu)
        {
            //printf("%d %d**2**\n",u,v);
            flag=0;
            continue;
        }
        if(dfn[v]==-1)
        {
            //printf("%d %d**3**\n",u,v);
            pre[v]=u;
            dfs(v,u);
            low[u]=min(low[u],low[v]);
            if(low[v]>dfn[u])
            {
                //printf("%d %d**666**\n",u,v);
                isbridge[v]=1;
                bridge_cnt++;
            }
        }
        else if(visit[v]) //printf("%d %d**4**\n",u,v),
            low[u]=min(dfn[v],low[u]);
    }
    //无环图找桥是不需要dfn[u]==low[u]这个判断的,具体为什么可以自己写一下
}
int lca(int u,int v)  //找到公共最近父节点
{
    int res=0;
    if(dfn[u]<dfn[v]) swap(u,v);
    while(dfn[u]>dfn[v])
    {
        if(isbridge[u])
        {
            isbridge[u]=0;
            res++;
        }
        u=pre[u];  //pre是u父亲节点
    }
    while(dfn[v]>dfn[u])
    {
        if(isbridge[v])
        {
            isbridge[v]=0;
            res++;
        }
        v=pre[v];
    }
    //经过上面两个while,这样dfn[u]==dfn[v]此时他们就到达了最近公共父节点
    return res;
}
int main()
{
    int n,m,t=0;
    while(~scanf("%d%d",&n,&m)  && (n || m))
    {
        for(int i=1;i<=n;++i)
        {
            w[i].clear();
        }
        int u,v;
        while(m--)
        {
            scanf("%d%d",&u,&v);
            w[u].push_back(v);
            w[v].push_back(u);
        }
        memset(dfn,-1,sizeof(dfn));
        memset(isbridge,0,sizeof(isbridge));
        memset(visit,0,sizeof(visit));
        depth=bridge_cnt=0;
        for(int i=1;i<=n;++i)  //输入的原图就是所有点都连接在一起,不会出现好几个连通图
            if(dfn[i]==-1)
                dfs(1,-1);
        //printf("%d**\n",bridge_cnt);
        int q;
        scanf("%d",&q);
        printf("Case %d:\n", ++t);
        while(q--)
        {
            scanf("%d%d",&u,&v);
            int ans=lca(u,v);
            bridge_cnt-=ans;
            printf("%d\n",bridge_cnt);
        }
        //printf("\n");
    }
    return 0;
}

 

posted @ 2019-10-13 10:18  kongbursi  阅读(212)  评论(0编辑  收藏  举报