zoukankan      html  css  js  c++  java
  • codeforces 178B


    题意:给一个n个点的无向图,m条双向边,保证没有重边和自环,图连通,有q个询问,给两个点,S和T,问从S到T有多少条割边。

    思路:看到这题第一反应就是求双连通分量,然后缩点,因为在同一个双连通分量内肯定没有割边,然后缩点后原图就变成了一棵树,因为保证原图连通,所以得到的也只有一颗树,树中的边即为原图中的割边,于是问题就转化成求树中两点的距离了,用LCA即可解决。先贴一个代码。

    #include <iostream>
    #include <string.h>
    #include <stdio.h>
    #include <algorithm>
    #define maxn 100010
    using namespace std;
    struct edge
    {
        int to;
        int next;
        int num;
    }e[3][maxn<<2];
    int box[3][maxn],cnt[3];
    void init()
    {
        memset(box,-1,sizeof(box));
        memset(cnt,0,sizeof(cnt));
    }
    void add(int from,int to,int num,int t)
    {
        e[t][cnt[t]].to=to;
        e[t][cnt[t]].num=num;
        e[t][cnt[t]].next=box[t][from];
        box[t][from]=cnt[t]++;
    }
    int pre[maxn];
    int low[maxn];
    int bridge[maxn];
    int bcnt=0;
    int cnt0;
    void bridge_search(int now,int fa)
    {
        int t;
        int v,w;
        low[now]=pre[now]=++cnt0;
        for(t=box[0][now];t+1;t=e[0][t].next)
        {
            v=e[0][t].to;
            if(v==fa)
            continue;
            if(!pre[v])
            {
                bridge_search(v,now);
                if(low[v]<low[now])
                low[now]=low[v];
                if(low[v]>pre[now])
                {
                    bridge[e[0][t].num]=1;
                }
            }
            else
            {
                if(low[now]>pre[v])
                low[now]=pre[v];
            }
        }
    }
    int Bridge(int n)
    {
        int i;
        cnt0=0;
        memset(pre,0,sizeof(pre));
        memset(low,0,sizeof(low));
        memset(bridge,0,sizeof(bridge));
        bcnt=0;
        for(i=1;i<=n;i++)
        {
            if(!pre[i])
            {
                bridge_search(i,0);
            }
        }
        return bcnt;
    }
    int vis[maxn];
    int dist[maxn];
    void Dfs(int now,int num)
    {
        low[now]=num;
        vis[now]=1;
        int t,v,nn;
        for(t=box[0][now];t+1;t=e[0][t].next)
        {
            v=e[0][t].to,nn=e[0][t].num;
            if(bridge[nn])
            continue;
            if(!vis[v])
            {
                Dfs(v,num);
            }
        }
    }
    void solve(int n)//Ëõµã
    {
       int i,sum=0;
       memset(low,0,sizeof(low));
       memset(vis,0,sizeof(vis));
       for(i=1;i<=n;i++)
       {
           if(!low[i])
           Dfs(i,++sum);
       }
       for(i=1;i<=n;i++)
       {
           int t,v;
           for(t=box[0][i];t+1;t=e[0][t].next)
           {
               v=e[0][t].to;
               if(low[i]!=low[v])
               {
                   add(low[i],low[v],0,1);
                   add(low[v],low[i],0,1);
               }
           }
       }
    }
    void dfs(int now,int deep)
    {
        dist[now]=deep;
        vis[now]=1;
        int t,v;
        for(t=box[1][now];t+1;t=e[1][t].next)
        {
            v=e[1][t].to;
            if(!vis[v])
            {
                dfs(v,deep+1);
            }
        }
    }
    int f[maxn];
    void finit(int n)
    {
        int i;
        for(i=0;i<=n;i++)
        f[i]=i;
    }
    int find(int x)
    {
        if(x==f[x])
        return x;
        return f[x]=find(f[x]);
    }
    int ans[maxn];
    void lca(int now)
    {
        f[now]=now;
        vis[now]=1;
        int t,v,x;
        for(t=box[1][now];t+1;t=e[1][t].next)
        {
            v=e[1][t].to;
            if(!vis[v])
            {
                lca(v);
                f[v]=now;
            }
        }
        for(t=box[2][now];t+1;t=e[2][t].next)
        {
            v=e[2][t].to,x=e[2][t].num;
            if(vis[v]==2)
            {
                int tt=find(v);
                ans[x]=dist[now]+dist[v]-2*dist[tt];
            }
        }
        vis[now]=2;
    }
    int main()
    {
        //freopen("dd.txt","r",stdin);
        int n,m,i,a,b,q;
        scanf("%d%d",&n,&m);
        init();
        for(i=1;i<=m;i++)
        {
            scanf("%d%d",&a,&b);
            add(a,b,i,0);
            add(b,a,i,0);
        }
        memset(ans,0,sizeof(ans));
        Bridge(n);
        solve(n);
        memset(vis,0,sizeof(vis));
        dfs(1,0);
        scanf("%d",&q);
        for(i=1;i<=q;i++)
        {
            scanf("%d%d",&a,&b);
            if(low[a]!=low[b])
            {
                add(low[a],low[b],i,2);
                add(low[b],low[a],i,2);
            }
        }
        memset(vis,0,sizeof(vis));
        lca(1);
        for(i=1;i<=q;i++)
        printf("%d\n",ans[i]);
        return 0;
    }
    


  • 相关阅读:
    【大话设计模式】——浅谈设计模式基础
    mongodb入门安装
    Unity3D研究之多语言用中文做KEY
    java7新特性之Try-with-resources (TWR)
    ORACLE取周、月、季、年的開始时间和结束时间
    topas命令详解
    topas解析(AIX)
    top(topas),vmstat,iostat在linux和AIX操作系统下显示情况
    怎么检查网站的死链接呢?
    网站死链接检测查询工具
  • 原文地址:https://www.cnblogs.com/javawebsoa/p/2990537.html
Copyright © 2011-2022 走看看