题干:
  为了从F(1≤F≤5000)个草场中的一个走到另一个,贝茜和她的同伴们有时不得不路过一些她们讨厌的可怕的树.奶牛们已经厌倦了被迫走某一条路,所以她们想建一些新路,使每一对草场之间都会至少有两条相互分离的路径,这样她们就有多一些选择.每对草场之间已经有至少一条路径.给出所有 R ( F - 1 ≤ R ≤ 10000 )条双向路的描述,每条路连接了两个不同的草场,请计算最少的新建道路的数量, 路径由若干道路首尾相连而成.两条路径相互分离,是指两条路径没有一条重合的道路.但是,两条分离的路径上可以有一些相同的草场. 对于同一对草场之间,可能已经有两条不同的道路,你也可以在它们之间再建一条道路,作为另一条不同的道路,请输出最少的需要新建的道路数.

题解:

  加减道路?加减边?比较简单地就可以想到边双连通分量。

  本题要求使每一个节点都可由至少两条道路到达,那么满足条件的节点就是度数 >= 2 的节点(无向图的度)。度数为 1 的节点就是不满足题意的。

  在两点间建边有三种情况:
  1、两个度数 >= 2 的节点相连:没用,舍掉。

  2、一个度数 >= 2 ,另一个 = 1 的两个节点相连:使一个节点满足题意。

  3、两个度数 = 1 的节点相连:使两个节点满足题意。

  十分显然,两个度数 = 1 的节点相连一定是最优的。这也表明,本题核心在于找到 度数 = 1 的节点。

100%  错解(点双连通分量):

  像以往的点双连通分量,先缩点,求一下度数即可。

  但这样的 AC 代码并不符合点双连通分量的求法(在实现过程中,需要在 tarjan 中判断掉父节点;在建边中,需要判掉重边)。

  只能说在这道题中,数据并没有考虑这种打法,虽然 AC,一定是错解。

Code:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #define $ 5111
 5 using namespace std;
 6 int m,n,k,t,dfn[$],low[$],first[$],tot1,tar,sta[$],up,circle,tr=-1;
 7 int sum,cir[$],out[$];
 8 bool judge[$],vis[$][$];
 9 struct tree{    int to,next;    }a[$<<5],aa[$<<5];
10 inline int min(int x,int y){    return x<y?x:y;    }
11 inline void add(int x,int y){
12     a[++tot1]=(tree){    y,first[x]    };
13     first[x]=tot1;
14     a[++tot1]=(tree){    x,first[y]    };
15     first[y]=tot1;
16 }
17 inline void tarjan(int x,int dad,int tmp=0){
18     dfn[x]=low[x]=++tar;
19     sta[++up]=x;
20     for(register int i=first[x];i;i=a[i].next){
21         int to=a[i].to;
22         if(to==dad) continue;
23         if(!dfn[to]){
24             tarjan(to,x);
25             low[x]=min(low[x],low[to]);
26         }
27         else low[x]=min(low[x],dfn[to]);
28     }
29     if(dfn[x]==low[x]){
30         ++circle;
31         do{
32             tmp=sta[up--];
33             cir[tmp]=circle;
34         }while(tmp!=x);
35     }
36 }
37 signed main(){
38     scanf("%d%d",&n,&m);
39     for(register int i=1,x,y;i<=m;++i){
40         scanf("%d%d",&x,&y);
41         if(vis[x][y]==0) add(x,y),vis[x][y]=vis[y][x]=1;
42     }
43     tarjan(1,0);
44     for(register int i=1;i<=n;++i)
45         for(register int j=first[i];j;j=a[j].next){
46             int to=a[j].to;
47             if(cir[i]!=cir[to]) out[cir[i]]++;
48         }
49     for(register int i=1;i<=circle;++i) if(out[i]<2) sum++;
50     circle==1?puts("0"):printf("%d\n",(sum+1)/2);
51 }

View Code

100%  正解(边双连通分量):

  正解当然是边双连通分量。

 1 inline void tarjan(int x,int opt){
 2     dfn[x]=low[x]=++tar;
 3     for(register int i=first[x];i;i=a[i].next){
 4         int to=a[i].to;
 5         if(!dfn[to]){
 6             tarjan(to,i);
 7             low[x]=min(low[x],low[to]);
 8             if(low[to]>dfn[x]) br[i]=br[i^1]=1;
 9         }
10         else if(i!=(opt^1)) low[x]=min(low[x],dfn[to]);
11     }
12 }
13 inline void dfs(int x){
14     in[x]=dcc;
15     for(register int i=first[x];i;i=a[i].next){
16         int to=a[i].to;
17         if(in[to]||br[i]) continue;
18         dfs(to);
19     }
20 }

  同样是先缩点,求一下度数即可。

Code:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #define $ 5111
 5 using namespace std;
 6 int m,n,sum,dfn[$],low[$],first[$],tot,tar,br[$],up,circle,dcc,in[$],out[$];
 7 struct tree{    int to,next;    }a[$<<5],aa[$<<5];
 8 inline int min(int x,int y){    return x<y?x:y;    }
 9 inline void add(int x,int y){
10     a[++tot]=(tree){    y,first[x]    };
11     first[x]=tot;
12     a[++tot]=(tree){    x,first[y]    };
13     first[y]=tot;
14 }
15 inline void tarjan(int x,int opt){
16     dfn[x]=low[x]=++tar;
17     for(register int i=first[x];i;i=a[i].next){
18         int to=a[i].to;
19         if(!dfn[to]){
20             tarjan(to,i);
21             low[x]=min(low[x],low[to]);
22             if(low[to]>dfn[x]) br[i]=br[i^1]=1;
23         }
24         else if(i!=(opt^1)) low[x]=min(low[x],dfn[to]);
25     }
26 }
27 inline void dfs(int x){
28     in[x]=dcc;
29     for(register int i=first[x];i;i=a[i].next){
30         int to=a[i].to;
31         if(in[to]||br[i]) continue;
32         dfs(to);
33     }
34 }
35 signed main(){
36     scanf("%d%d",&n,&m); tot++;
37     for(register int i=1,x,y;i<=m;++i) scanf("%d%d",&x,&y),add(x,y);
38     tarjan(1,0);
39     for(register int i=1;i<=n;++i)  if(!in[i]) dcc++,dfs(i);
40     for(register int i=2,x,y;i<=tot;++i){
41         x=a[i^1].to,y=a[i].to;
42         if(in[x]!=in[y]) out[in[y]]++;
43     }
44     for(register int i=1;i<=dcc;++i) if(out[i]==1) sum++;
45     dcc==1?puts("0"):printf("%d\n",(sum+1)/2);
46 }

View Code

转载于:https://www.cnblogs.com/OI-zzyy/p/11183705.html

Redundant Paths 分离的路径(边双连通分量)相关推荐

  1. [BZOJ1718]:[Usaco2006 Jan] Redundant Paths 分离的路径(塔尖)

    题目传送门 题目描述 为了从F个草场中的一个走到另一个,贝茜和她的同伴们有时不得不路过一些她们讨厌的可怕的树.奶牛们已经厌倦了被迫走某一条路,所以她们想建一些新路,使每一对草场之间都会至少有两条相互分 ...

  2. bzoj 1718: [Usaco2006 Jan] Redundant Paths 分离的路径

    题意 给你一个无向图 问你最少添加多少条边可以使得他变成边双图 题解 直接双连通缩点 得到一颗树 然后答案是叶子节点/2向上取整 取法是每一次找两个LCA深度最小的叶子,两个连边就可以了 然后不知道为 ...

  3. 图论学习-无向图双连通分量

    文章目录 无向图双连通分量 1.基本术语与概念 1.1.割点 1.2.桥 1.3.边双连通分量 (e-DCC) 1.4 点双连通分量 (v-DCC) 1.5 时间戳 2.求解 2.1 边双连通分量 2 ...

  4. Redundant Paths POJ - 3177(tarjan+边双连通分量)

    题意: 有n个牧场,要求从一个牧场到另一个牧场,要求至少要有2条独立的路可以走.现已有m条路,求至少要新建多少条路,使得任何两个牧场之间至少有两条独立的路.两条独立的路是指:没有公共边的路,但可以经过 ...

  5. 【POJ - 3177】Redundant Paths(边双连通分量,去重边)

    题干: In order to get from one of the F (1 <= F <= 5,000) grazing fields (which are numbered 1.. ...

  6. POJ 3177 Redundant Paths(边双联通分量)

    题目描述: In order to get from one of the F (1 <= F <= 5,000) grazing fields (which are numbered 1 ...

  7. [POJ3177]Redundant Paths(双联通)

    在看了春晚小彩旗的E技能(旋转)后就一直在lol--额抽点时间撸一题吧-- Redundant Paths Time Limit: 1000MS   Memory Limit: 65536K Tota ...

  8. POJ 3177 Redundant Paths (边双连通+缩点)

    <题目链接> <转载于 >>>  > 题目大意: 有n个牧场,Bessie 要从一个牧场到另一个牧场,要求至少要有2条独立的路可以走.现已有m条路,求至少要新 ...

  9. POJ 3177 Redundant Paths POJ 3352 Road Construction(双连接)

    POJ 3177 Redundant Paths POJ 3352 Road Construction 题目链接 题意:两题一样的.一份代码能交.给定一个连通无向图,问加几条边能使得图变成一个双连通图 ...

最新文章

  1. 铁大Facebook——电梯演讲
  2. WARNING:Your password has expired --linux 用户密码过期
  3. SPOJ7258(后缀自动机--第k大的子串)
  4. Linux 内存管理 | 物理内存、内存碎片、伙伴系统、SLAB分配器
  5. 001 Python中的变量和字符串
  6. UOJ#269. 【清华集训2016】如何优雅地求和
  7. css3的那些高级选择器一
  8. 安卓手机卡顿基础优化教程
  9. 转载:在Python 3中使用深度森林(Deep Forest)进行分类
  10. Win10系统异常应该怎么修复
  11. 视频:忆童年有摇杆,《暗黑破坏神3》街机版演示
  12. 阿里云数据盘挂载完整过程
  13. 恶意软件通信协议的应用现状分析
  14. Android之高德地图SDK配置及简单使用详解
  15. ardupilot GPS代码分析
  16. 心紊妥布俅善市陀炎妇涣上街彻躺
  17. 天天打骂孩子对孩子有什么影响
  18. 高等代数-三阶特征根、特征向量求解详细过程
  19. 手把手教你创建个人微信公众号
  20. discord Bot 实现机器人发送私信验证码

热门文章

  1. QT 添加资源.qrc文件(My Sources File 图片 音频 支持翻译的.qm文件)
  2. android开发 pdf阅读器 第三方可,android pdf 阅读器开发, pdf demo, pdf第三方控件
  3. 深入理解并发编程之CAS无锁机制与ABA问题
  4. 资料打印字体大小多少合适,去哪里打印资料
  5. Windows下使用bat批处理文件实现进程守护
  6. mysql出现Error writing file \'xxx\'( Errcode:28)的问题
  7. sdkmanager工具安装
  8. 华为ME60、S9306从设备观看光模块收/发光命令
  9. [SSD固态硬盘技术 6] DRAM缓存技术详解
  10. 匿名函数的表达式可以有多个吗python_匿字的意思、匿的繁体字、匿的笔顺笔画、匿字部首和繁体字匿的意思...