Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 265|回复: 0

[默认分类] Redundant Paths POJ - 3177(边双连通分量&&缩点)

[复制链接]
  • TA的每日心情
    开心
    2021-12-13 21:45
  • 签到天数: 15 天

    [LV.4]偶尔看看III

    发表于 2018-4-26 14:29:05 | 显示全部楼层 |阅读模式

    题目链接
    Redundant Paths POJ - 3177
    题意
    有F个牧场,1<=F<=5000,现在一个牧群经常需要从一个牧场迁移到另一个牧场。奶牛们已经厌烦老是走同一条路,所以有必要再新修几条路,这样它们从一个牧场迁移到另一个牧场时总是可以选择至少两条独立的路。现在F个牧场的任何两个牧场之间已经至少有一条路了,奶牛们需要至少有两条。
    给定现有的R条直接连接两个牧场的路,F-1<=R<=10000,计算至少需要新修多少条直接连接两个牧场的路,使得任何两个牧场之间至少有两条独立的路。两条独立的路是指没有公共边的路,但可以经过同一个中间顶点。
    分析
    抽象成图论模型:给定一个连通图,求至少加多少条边使得这个图是一个边双连通图。
    求出边双连通分量,将每个边双连通分量缩成一个点,这样原图就变成一个树图。我们只要找到所有在树图中度数为1的点,将其两两连边,使得每个点的度数都大于等于2即可。
    求边双连通分量用tarjan算法,时间复杂度为O(n+m)。找度数为1的点的时间复杂度为O(n+m)。所以总时间复杂度为O(n+m)。
    需要注意的是题干未说明没有重边,所以在建图的时候需要自己去掉重边。
    代码
    1. [code]#include <iostream>
    2. #include <cstdio>
    3. #include <vector>
    4. #include <cstring>
    5. #include <stack>
    6. using namespace std;
    7. const int maxn=5e3+100;
    8. vector<int> g[maxn];
    9. int n,m,par[maxn],du[maxn];
    10. int dfn[maxn],low[maxn];
    11. stack<int> sta;
    12. bool map[maxn][maxn];
    13. void tarjan(int u,int fa,int dep)
    14. {
    15.     dfn[u]=low[u]=dep;
    16.     sta.push(u);
    17.     for(int i=0;i<g[u].size();i++)
    18.     {
    19.         int v=g[u][i];
    20.         if(v==fa) continue;
    21.         if(dfn[v])
    22.             low[u]=min(low[u],dfn[v]);
    23.         else
    24.         {
    25.             tarjan(v,u,dep+1);
    26.             low[u]=min(low[u],low[v]);
    27.         }
    28.     }
    29.     if(dfn[u]==low[u])
    30.     {
    31.         while(!sta.empty())
    32.         {
    33.             int tmp=sta.top();sta.pop();
    34.             par[tmp]=u;
    35.             if(tmp==u) break;
    36.         }
    37.     }
    38. }
    39. void solve()
    40. {
    41.     for(int i=1;i<=n;i++)
    42.     {
    43.         for(int j=0;j<g[i].size();j++)
    44.         {
    45.             int x=par[i];
    46.             int y=par[g[i][j]];
    47.             if(x!=y)
    48.                 du[x]++;
    49.         }
    50.     }
    51.     int sum=0;
    52.     for(int i=1;i<=n;i++)
    53.         if(du[i]==1)
    54.         sum++;
    55.     printf("%d\n",(sum+1)/2);
    56. }
    57. int main()
    58. {
    59.     while(~scanf("%d%d",&n,&m))
    60.     {
    61.         memset(du,0,sizeof(du));
    62.         memset(dfn,0,sizeof(dfn));
    63.         memset(low,0,sizeof(low));
    64.         memset(map,false,sizeof(map));
    65.         for(int i=0;i<=n;i++) par[i]=i;
    66.         for(int i=0;i<m;i++)
    67.         {
    68.             int u,v;
    69.             scanf("%d%d",&u,&v);
    70.             if(!map[u][v])//注意重边
    71.             {
    72.                 g[u].push_back(v);
    73.                 g[v].push_back(u);
    74.                 map[u][v]=map[v][u]=true;
    75.             }
    76.         }
    77.         tarjan(1,-1,1);
    78.         solve();
    79.         for(int i=0;i<=n;i++) g[i].clear();
    80.     }
    81.     return 0;
    82. }
    复制代码
    [/code]

    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-5-17 00:49 , Processed in 0.415902 second(s), 37 queries .

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc.

    快速回复 返回顶部 返回列表