• 图论:桥


    UVA796:利用Tarjan求无向图的割边(桥)

    Tarjan求割边和求割点的差异不大

    int n,deep,root,cnt;
    int g[maxn],dfn[maxn],low[maxn];
    struct Edge{int t,w,next;}e[maxm];
    map<int,map<int,int> > mp;
    vector<pair<int,int> > bridge;

    这里有的变量在上一篇博文中已经介绍过了

    我们看到mp映射是用来替代二维数组进行判重的

    本来打算换成hash_map但是发现并不好用,这是个必须要补的坑

    这里的判重是判断是否有重边,由于权重都是1所以并不需要进行更新边权

    由于是使用的邻接表来存的图,所以判重不是很方便

    可以先读成邻接矩阵再转存邻接表

    bridge就是我们求出来的所有的桥

    int tarjan(int u,int fa)
    {
        int lowu;
        lowu=dfn[u]=++deep;
        for(int tmp=g[u];tmp;tmp=e[tmp].next)
        {
            int v=e[tmp].t;
            if(!dfn[v])
            {
                int lowv=tarjan(v,u);
                lowu=min(lowu,lowv);
                if(lowv>dfn[u])
                {
                    int from,to;from=u;to=v;
                    if(from>to) swap(from,to);
                    bridge.push_back(make_pair(from,to));
                }
            }
            else if(v!=fa&&dfn[v]<dfn[u])
                lowu=min(lowu,dfn[v]);
        }
        low[u]=lowu;
        return lowu;
    }
    int tarjan(int u,int fa)
    {
        int lowu;
        lowu=dfn[u]=++deep;
        for(int tmp=g[u];tmp;tmp=e[tmp].next)
        {
            int v=e[tmp].t;
            if(!dfn[v])
            {
                int lowv=tarjan(v,u);
                lowu=min(lowu,lowv);
                if(lowv>dfn[u])
                {
                    int from,to;from=u;to=v;
                    if(from>to) swap(from,to);
                    bridge.push_back(make_pair(from,to));
                }
            }
            else if(v!=fa&&dfn[v]<dfn[u])
                lowu=min(lowu,dfn[v]);
        }
        low[u]=lowu;
        return lowu;
    }
    int tarjan(int u,int fa)
    {
        int lowu;
        lowu=dfn[u]=++deep;
        for(int tmp=g[u];tmp;tmp=e[tmp].next)
        {
            int v=e[tmp].t;
            if(!dfn[v])
            {
                int lowv=tarjan(v,u);
                lowu=min(lowu,lowv);
                if(lowv>dfn[u])
                {
                    int from,to;from=u;to=v;
                    if(from>to) swap(from,to);
                    bridge.push_back(make_pair(from,to));
                }
            }
            else if(v!=fa&&dfn[v]<dfn[u])
                lowu=min(lowu,dfn[v]);
        }
        low[u]=lowu;
        return lowu;
    }

    以上是求割边的Tarjan

    最后给出完整实现,题目说了要排序,那就排序吧。把求出来的桥排序

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<vector>
     4 #include<map>
     5 #include<algorithm>
     6 using namespace std;
     7 const int maxn=10005;
     8 const int maxm=100005;
     9 int n,deep,root,cnt;
    10 int g[maxn],dfn[maxn],low[maxn];
    11 struct Edge{int t,w,next;}e[maxm];
    12 map<int,map<int,int> > mp;
    13 vector<pair<int,int> > bridge;
    14 bool cmp(pair<int,int> x,pair<int,int> y)
    15 {
    16     if(x.first!=y.first)
    17         return  x.first<y.first;
    18     else return x.second<y.second;
    19 }
    20 void addedge(int u,int v,int w)
    21 {
    22     if(mp[u][v]==1) return;
    23     else {mp[u][v]=1;}  
    24     e[++cnt].t=v;e[cnt].w=w;
    25     e[cnt].next=g[u];g[u]=cnt;
    26 }
    27 int tarjan(int u,int fa)
    28 {
    29     int lowu;
    30     lowu=dfn[u]=++deep;
    31     for(int tmp=g[u];tmp;tmp=e[tmp].next)
    32     {
    33         int v=e[tmp].t;
    34         if(!dfn[v])
    35         {
    36             int lowv=tarjan(v,u);
    37             lowu=min(lowu,lowv);
    38             if(lowv>dfn[u])
    39             {
    40                 int from,to;from=u;to=v;
    41                 if(from>to) swap(from,to);
    42                 bridge.push_back(make_pair(from,to));
    43             }
    44         }
    45         else if(v!=fa&&dfn[v]<dfn[u])
    46             lowu=min(lowu,dfn[v]);
    47     }
    48     low[u]=lowu;
    49     return lowu;
    50 }
    51 int main()
    52 {
    53     while(scanf("%d",&n)==1)
    54     {
    55         deep=cnt=0;
    56         memset(g,0,sizeof(g));
    57         memset(dfn,0,sizeof(dfn));
    58         memset(low,0,sizeof(low));
    59         memset(e,0,sizeof(e));
    60         mp.clear();
    61         bridge.clear();
    62         int u,v,m;
    63         for(int i=1;i<=n;i++)
    64         {
    65             scanf("%d (%d)",&u,&m);
    66             for(int j=1;j<=m;j++)
    67                 scanf("%d",&v),addedge(u,v,1);
    68         }
    69         for(int i=1;i<=n;i++)
    70             if(!dfn[i]) {root=i;tarjan(i,-1);}
    71         printf("%d critical links
    ",bridge.size());
    72         sort(bridge.begin(),bridge.end(),cmp);
    73         for(int i=0;i<bridge.size();i++)
    74             printf("%d - %d
    ",bridge[i].first,bridge[i].second);
    75         printf("
    ");
    76     }
    77     return 0;
    78 }
  • 相关阅读:
    自定义ProgressBar
    Anroid开发中常用快捷键
    Intent用法
    IO(Input Output)流
    自定义Dialog
    仿UC点击两次返回键退出程序
    横竖屏切换时Activity的生命周期
    单例模式
    Timer用法
    关于数组
  • 原文地址:https://www.cnblogs.com/aininot260/p/9428605.html
Copyright © 2020-2023  润新知