无向图概念:(这里的x->y表示x和y之间有一条无向边
1.桥:对于一个无向图,如果删除某条边后,该图的连通分量增加,则称这条边为桥

比如1->2->3->4这样一个简单得图一共有3个桥,分别是1->2,2->3,3->4

1->2->3->4->1 这样就没有桥,因为删除任意一个边,任意两点还可以互相往来(因为是双向边嘛)

2.割点/割项:对于一个无向图,如果删除某个节点u后,该图的连通分量增加,则节点u为割项或关节点

1->2->3->4 这样的图有2个割点,分别是2,3

1->2->3->4->1这样的图也是没有割点的,删除任意一个点其他点还是可以往来的

3.点-双联通:对于一个连通图,如果任意两点至少存在两条点不重复路径(即在从x走到y,如果删除任意一个其他点还可以从x走到y),
  则称这个图为点双连通(也就是通常说的的双联通) 这样的图没有割点

4.边-双联通:对于一个连通图,如果任意两点至少存在两条边不重复路径,则称该图为边双连通的

这样的图没有割边

题意:

贝西和牛群被迫从一片标着1..F的牧场走到另一片牧场,他们必须在烂苹果树附近穿过。奶牛现在已经厌倦了经常被迫走一条特定的路,想要建一些新的路,这样它们就可以在任何一对田地之间至少有两条不同的路可选。他们目前在每对字段之间至少有一条路由,并且希望至少有两条路由。

题解:

那我们可以把所有割边都消除了就可以了

我们通过看图可以发现,割边一般是存在在一个点只与其他所有点有且仅有一条无向边

因为题目上已经保证了任意两点之间至少有一条路,所有我们找到所有这样的点,让它们互相连起来就可以了

黑边是原图的,红边是添加后使图变成边-双连通图的

根据上面描述,2,3,4都属于这样的点,我们就需要2条边就可以使它变成双连通图

根据上面描述,2,3,4,5都属于这样的点,我们就需要2条边就可以使它变成双连通图

这样的话,任意一个点到达其他点至少有两条路径

代码1:

 1 #include<stdio.h>
2 #include<string.h>
3 #include<iostream>
4 #include<algorithm>
5 #include<map>
6 using namespace std;
7 const int maxn=5010;
8 int head[maxn],cnt,num,stacks[maxn],top,cut,in[maxn],out[maxn];
9 struct edge
10 {
11 int v,next;
12 }e[maxn];
13 int visit[maxn],belong[maxn],dfn[maxn],low[maxn];
14 void add_edge(int x,int y)
15 {
16 e[cnt].v=y;
17 e[cnt].next=head[x];
18 head[x]=cnt++;
19 }
20 void init()
21 {
22 memset(in,0,sizeof(in));
23 memset(out,0,sizeof(out));
24 memset(head,-1,sizeof(head));
25 cnt=num=top=cut=0;
26 }
27 void tarjan(int x,int pre)
28 {
29 low[x]=dfn[x]=++num;
30 visit[x]=1;
31 stacks[top++]=x;
32 int flag=1;
33 for(int i=head[x];i!=-1;i=e[i].next)
34 {
35 int v=e[i].v;
36 if(v==pre && flag)
37 {
38 flag=0;
39 continue;
40 }
41 if(!dfn[v])
42 {
43 tarjan(v,x);
44 low[x]=min(low[x],low[v]);
45 }
46 else if(visit[v])
47 {
48 low[x]=min(low[x],dfn[v]);
49 }
50 }
51 if(low[x]==dfn[x])
52 {
53 cut++;
54 int v;
55 while(true)
56 {
57 v=stacks[top-1];
58 top--;
59 belong[v]=cut;
60 visit[v]=0;
61 if(v==x) break;
62 //printf("*");
63 }
64 }
65 }
66 int main()
67 {
68 int n,m;
69 init();
70 scanf("%d%d",&n,&m);
71 while(m--)
72 {
73 int x,y;
74 scanf("%d%d",&x,&y);
75 add_edge(x,y);
76 add_edge(y,x);
77 }
78 tarjan(1,-1);
79 //printf("**\n");
80 for(int i=1;i<=n;++i)
81 {
82 for(int j=head[i];j!=-1;j=e[j].next)
83 {
84 int v=e[j].v;
85 if(belong[i]!=belong[v])
86 {
87 in[belong[v]]++;
88 out[belong[i]]++;
89 }
90 }
91 }
92 int ans=0;
93 for(int i=1;i<=n;++i)
94 {
95 if(out[i]==1)
96 ans++;
97 }
98 printf("%d\n",(ans+1)/2);
99 }

代码2:

  1 //time 1031MS
2
3 //memory 31340K
4
5 #pragma comment(linker, "/STACK:1024000000,1024000000")
6
7 #include <iostream>
8
9 #include <cstdio>
10
11 #include <cstdlib>
12
13 #include <cstring>
14
15 #define MAXN 300015
16
17 #define MAXM 4000015
18
19 using namespace std;
20
21 struct Edge{
22
23 int v,next;
24
25 }e[MAXM];
26
27 int head[MAXN],en;
28
29 int head2[MAXN],en2;
30
31 int belong[MAXN],dfn[MAXN],low[MAXN],sta[MAXN],top,num,scc;
32
33 int in[MAXN],out[MAXN];
34
35 bool vis[MAXN];
36
37 void init()
38
39 {
40
41 memset(head,-1,sizeof(head));
42
43 memset(vis,0,sizeof(vis));
44
45 en = 0;
46
47 top = 0;
48
49 scc=num = 0;memset(dfn,0,sizeof(dfn));
50
51 }
52
53 void addedge(int u,int v)
54
55 {
56
57 e[en].v = v;
58
59 e[en].next = head[u];
60
61 head[u] = en++;
62
63 }
64
65 //void addedge2(int u,int v)
66 //
67 //{
68 //
69 // edge2[en2].v = v;
70 //
71 // edge2[en2].next = head2[u];
72 //
73 // head2[u] = en2++;
74 //
75 //}
76
77 void tarjan(int u,int fa)
78
79 {
80
81 dfn[u] = low[u] = ++num;
82
83 sta[++top] = u;
84
85 int cnt=0;
86
87 for(int i = head[u]; i != -1; i = e[i].next)
88
89 {
90
91 int v = e[i].v;
92
93 if(!dfn[v])
94
95 {
96
97 tarjan(v,u);
98
99 low[u] = min(low[u],low[v]);
100
101 }
102
103 else if (fa==v)
104
105 {
106
107 if (cnt) low[u] = min(low[u],dfn[v]);//重边
108
109 cnt++;
110
111 }
112
113 else low[u] = min(low[u],dfn[v]);
114
115 }
116
117 if(dfn[u]==low[u])
118
119 {
120
121 int x;
122
123 scc++;
124
125 do
126
127 {
128
129 x = sta[top--];
130
131 belong[x] = scc;
132
133 }while(x!=u);
134
135 }
136
137 }
138
139 //void build()
140 //
141 //{
142 //
143 // en2 = 0;
144 //
145 // memset(head2,-1,sizeof(head2));
146 //
147 // for(int i = 1; i <= n; i++)
148 //
149 // {
150 //
151 // for(int j = head[i]; j!=-1; j = e[j].next)
152 //
153 // {
154 //
155 // int v = e[j].v;
156 //
157 // if(belong[i]!=belong[v])
158 //
159 // addedge2(belong[i],belong[v]);
160 //
161 // }
162 //
163 // }
164 //
165 //}
166
167 int ans;
168
169 //int dfs(int u,int p)
170 //
171 //{
172 //
173 // int max1=0,max2=0;
174 //
175 // for (int i=head2[u];i!=-1;i=edge2[i].next)
176 //
177 // {
178 //
179 // int v=edge2[i].v;
180 //
181 // if (v==p) continue;
182 //
183 // int tmp=dfs(v,u)+1;
184 //
185 // if (max1<tmp) max2=max1,max1=tmp;
186 //
187 // else if (max2<tmp) max2=tmp;
188 //
189 // }
190 //
191 // ans=max(ans,max1+max2);
192 //
193 // return max1;
194 //
195 //}
196 int main()
197 {
198 int n,m;
199 init();
200 scanf("%d%d",&n,&m);
201 while(m--)
202 {
203 int x,y;
204 scanf("%d%d",&x,&y);
205 addedge(x,y);
206 addedge(y,x);
207 }
208 tarjan(1,-1);
209 //printf("**\n");
210 for(int i=1;i<=n;++i)
211 {
212 for(int j=head[i];j!=-1;j=e[j].next)
213 {
214 int v=e[j].v;
215 if(belong[i]!=belong[v])
216 {
217 in[belong[v]]++;
218 out[belong[i]]++;
219 }
220 }
221 }
222 int ans=0;
223 for(int i=1;i<=n;++i)
224 {
225 if(out[i]==1)
226 ans++;
227 }
228 printf("%d\n",(ans+1)/2);
229 }
230 //int main()
231 //
232 //{
233 //
234 // //freopen("/home/qitaishui/code/in.txt","r",stdin);
235 //
236 // int u,v;
237 //
238 // while(scanf("%d%d",&n,&m)&&(n+m))
239 //
240 // {
241 //
242 // init();
243 //
244 // //cout<<n<<m<<endl;
245 //
246 // for(int i = 0; i < m; i++)
247 //
248 // {
249 //
250 // scanf("%d%d",&u,&v);
251 //
252 // if (v==u) continue;
253 //
254 // addedge(u,v);
255 //
256 // addedge(v,u);
257 //
258 // //cout<<u<<" "<<v<<endl;
259 //
260 // }
261 //
262 //
263 //
264 // tarjan(1,-1);
265 //
266 // build();
267 //
268 // ans=0;
269 //
270 // dfs(1,-1);
271 //
272 // printf("%d\n",scc-ans-1);
273 //
274 // }
275 //
276 // return 0;
277 //
278 //}

Redundant Paths POJ - 3177 把原图变成边—双连通图的更多相关文章

  1. (连通图 ) Redundant Paths --POJ --3177

    链接: http://poj.org/problem?id=3177 http://acm.hust.edu.cn/vjudge/contest/view.action?cid=82833#probl ...

  2. E - Redundant Paths - poj 3177(缩点求叶子节点)

    题意:给一个图,想让每两个点之间都有两条路相连,不过特殊的是相同的两点之间多次相连被认为是一条边,现在求最少还需要添加几条边才能做到 分析:手欠没看清楚是相同的边只能相连一次,需要去重边,缩点后求出来 ...

  3. Redundant Paths POJ - 3177(边—双连通分量)

    题意: 在图中加边 看最少能通过加多少条边把 图变成边—双连通分量 解析: 先做一次dfs,不同的连通分量的low是不同的  注意重边 缩点 统计度为1的点  那么需要加的边为(ret+1)/2 #i ...

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

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

  5. POJ 3177 Redundant Paths POJ 3352 Road Construction

    这两题是一样的,代码完全一样. 就是给了一个连通图,问加多少条边可以变成边双连通. 去掉桥,其余的连通分支就是边双连通分支了.一个有桥的连通图要变成边双连通图的话,把双连通子图收缩为一个点,形成一颗树 ...

  6. POJ 3177 Redundant Paths & POJ 3352 Road Construction(双连通分量)

    Description In order to get from one of the F (1 <= F <= 5,000) grazing fields (which are numb ...

  7. POJ 3177 (Redundant Paths) —— (有重边,边双联通,无向图缩点)

    做到这里以后,总算是觉得tarjan算法已经有点入门了. 这题的题意是,给出若干个点和若干条边连接他们,在这个无向图中,问至少增加多少条边可以使得这个图变成边双联通图(即任意两点间都有至少两条没有重复 ...

  8. POJ 3177 Redundant Paths(边双连通的构造)

    Redundant Paths Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 13717   Accepted: 5824 ...

  9. tarjan算法求桥双连通分量 POJ 3177 Redundant Paths

    POJ 3177 Redundant Paths Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 12598   Accept ...

随机推荐

  1. 我们NetCore下日志存储设计

    日志的分类 首先往大的来说,日志分2种 ①业务日志: 即业务系统需要查看的日志, 常见的比如谁什么时候修改了什么. ②参数日志: 一般是开发人员遇到问题的时候定位用的, 一般不需要再业务系统里展示. ...

  2. MyISAM与InnoDB两者之间区别与选择(转)

    Mysql在V5.1之前默认存储引擎是MyISAM:在此之后默认存储引擎是InnoDB MyISAM:默认表类型,它是基于传统的ISAM类型,ISAM是Indexed Sequential Acces ...

  3. STM32驱动LCD实战

    前段时间写了<STM32驱动LCD原理>和<STM32的FSMC外设简介>两篇文章,本文将对STM32驱动LCD进行实战应用.LCD是深圳市拓普微科技开发有限公司的LMT028 ...

  4. ES6在工作中会用到的核心知识点讲解

    一.var, let, const 谈到ES6,估计大家首先肯定会想到var,let,const 咱就先谈谈这三者的区别 var a = 3; { var a = 4; } console.log(a ...

  5. Paginator Django 分页 When QuerySets are evaluated QuerySets 执行原理 QuerySets are lazy 惰性执行 访问db取数据的时机

    https://docs.djangoproject.com/en/2.2/topics/pagination/ Paginator objects¶ The Paginator class has ...

  6. list中map 的value值时间排序

    public static void main(String[] args) { String sys=DateUtil.getTime().substring(0,5); System.out.pr ...

  7. Solon rpc 1.3.1 发布,推出Cloud接口与配置规范

    Solon 是一个微型的Java RPC开发框架.项目从2018年启动以来,参考过大量前人作品:历时两年,3500多次的commit:内核保持0.1m的身材,超高的跑分,良好的使用体验.支持:Rpc. ...

  8. cms_文章管理

    文章管理 文章管理前端页面 把引入的多个布局抽成了公共代码 <%@ page language="java" contentType="text/html; cha ...

  9. 通过 JFR 与日志深入探索 JVM - TLAB 原理详解

    全系列目录:通过 JFR 与日志深入探索 JVM - 总览篇 什么是 TLAB? TLAB(Thread Local Allocation Buffer)线程本地分配缓存区,这是一个线程专用的内存分配 ...

  10. java获取post请求头部字符串

    尝试过很多方式,下面的方式最有效: 用获取数据流的方式,直接获取post过来的所有数据流 // 读取请求内容 BufferedReader br = new BufferedReader(new In ...