图论:桥

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\n",bridge.size());
72         sort(bridge.begin(),bridge.end(),cmp);
73         for(int i=0;i<bridge.size();i++)
74             printf("%d - %d\n",bridge[i].first,bridge[i].second);
75         printf("\n");
76     }
77     return 0;
78 }

 

转载于:https://www.cnblogs.com/aininot260/p/9428605.html

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值