Redundant Paths POJ - 3177 把原图变成边—双连通图
无向图概念:(这里的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 把原图变成边—双连通图的更多相关文章
- (连通图 ) Redundant Paths --POJ --3177
链接: http://poj.org/problem?id=3177 http://acm.hust.edu.cn/vjudge/contest/view.action?cid=82833#probl ...
- E - Redundant Paths - poj 3177(缩点求叶子节点)
题意:给一个图,想让每两个点之间都有两条路相连,不过特殊的是相同的两点之间多次相连被认为是一条边,现在求最少还需要添加几条边才能做到 分析:手欠没看清楚是相同的边只能相连一次,需要去重边,缩点后求出来 ...
- Redundant Paths POJ - 3177(边—双连通分量)
题意: 在图中加边 看最少能通过加多少条边把 图变成边—双连通分量 解析: 先做一次dfs,不同的连通分量的low是不同的 注意重边 缩点 统计度为1的点 那么需要加的边为(ret+1)/2 #i ...
- POJ 3177 Redundant Paths POJ 3352 Road Construction(双连接)
POJ 3177 Redundant Paths POJ 3352 Road Construction 题目链接 题意:两题一样的.一份代码能交.给定一个连通无向图,问加几条边能使得图变成一个双连通图 ...
- POJ 3177 Redundant Paths POJ 3352 Road Construction
这两题是一样的,代码完全一样. 就是给了一个连通图,问加多少条边可以变成边双连通. 去掉桥,其余的连通分支就是边双连通分支了.一个有桥的连通图要变成边双连通图的话,把双连通子图收缩为一个点,形成一颗树 ...
- 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 ...
- POJ 3177 (Redundant Paths) —— (有重边,边双联通,无向图缩点)
做到这里以后,总算是觉得tarjan算法已经有点入门了. 这题的题意是,给出若干个点和若干条边连接他们,在这个无向图中,问至少增加多少条边可以使得这个图变成边双联通图(即任意两点间都有至少两条没有重复 ...
- POJ 3177 Redundant Paths(边双连通的构造)
Redundant Paths Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 13717 Accepted: 5824 ...
- tarjan算法求桥双连通分量 POJ 3177 Redundant Paths
POJ 3177 Redundant Paths Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 12598 Accept ...
随机推荐
- jenkins 构建历史 显示版本号
0 jenkins 安装此插件: 此插件名为 " groovy postbuild " 1 效果图: 2 安装插件: 系统管理 --> 插件管理 --> 可选 ...
- ansible 安装和使用
ansible 安装和使用 ## 安装epel 源: rpm -ivh https://dl.fedoraproject.org/pub/e ...
- Docker学习笔记之搭建Docker私有仓库
Docker仓库服务器名为Docker注册(registry)服务器.可以使用docker push命令将镜像上传到注册服务器,也可以使用docker pull命令下载服务器的镜像. Docker注册 ...
- LR参数
一.LR函数 : lr_start_transaction: 为性能分析标记事务的开始 lr_end_transaction: 为性能分析标记事务的结束:事务名称与事务开始时保持一致 lr_ren ...
- linux下删除文件夹及下面所有文件
使用rm -rf 目录名字 命令即可 -r 就是向下递归,不管有多少级目录,一并删除-f 就是直接强行删除,不作任何提示的意思 rm 不带参数 只能删除文件 rm test.txt mkdir /us ...
- JAVA中@Override的含义
@Override是伪代码,表示重写(当然不写也可以),不过写上有如下好处: 1.可以当注释用,方便阅读: 2.编译器可以给你验证@Override下面的方法名是否是你父类中所有的,如果没有则报错.例 ...
- vue中computed/method/watch的区别
摘要:本文通过官方文档结合源码来分析computed/method/watch的区别. Tips:本文分析的源码版本是v2.6.11,文章中牵涉到vue响应式系统原理部分,如果不是很了解,建议先阅读上 ...
- FPGA仿真的概念及语法特点
以下是特权同学<FPGA设计+实战演练>书中的描述: 一个正规的设计需要花费在验证上的工作量,往往可能会占到整个开发流程的70%左右.验证通常分为仿真验证和板机验证. ...
- vue3.0 composition API
一.Setup函数 1.创建时间:组件创建之前被调用,优先与created被调用,this指向的实例为window,created所指向的实例为proxy 2.this指向:不会指向组件实例 3.参数 ...
- 记录list.remove()和list.pop()
list.remove(obj):这个是移除列表中某个值的第一个匹配项 list.pop(index):这个是移除列表中下标为index的元素 当元素全是数字或者有数字时注意区分.