无向图概念:(这里的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 //}

最新文章

  1. android view 中各函数的执行顺数
  2. xshell 终端窗口目录显示为深蓝色的不易分辨问题
  3. IIS WebForm开发基础
  4. 使用Nexus搭建Maven私服
  5. webservice之XFire的使用(java调用java)
  6. oracle存储过程实例
  7. Android利用Looper在子线程中改变UI
  8. bzoj 1089 [SCOI2003]严格n元树(DP+高精度)
  9. WPF学习(10)模板
  10. svg defs 进行定义 引用
  11. 同网段电脑互ping
  12. Winform DevExpress控件库(二) 使用SplashScreenManager控件定制程序加载页面
  13. android:background=&quot;@color/white&quot; [create file color.xml at res/values/]
  14. PAT1094:The Largest Generation
  15. TestNG进行接口测试,脚本及可维护性框架
  16. 下载Eclipse、下载Java各个版本,来这里就对了
  17. C# 注册机功能开发,机器码设计
  18. [cmd] rsync - 远程同步工具
  19. 1.App爬取相关库的安装(安装Charles及手机端证书安装配置)
  20. ios 判断app程序第一次启动方法

热门文章

  1. Python基础语法2-数据类型
  2. Session、Cookie与Token
  3. 使用msys2在window下构建和使用Linux的软件
  4. ctfhub技能树—彩蛋
  5. MySQL调优用户监控之show processlist
  6. 第一个 Maven 应用程序
  7. Scalable Go Scheduler Design Doc
  8. MySQL如何安全的给小表加字段
  9. Java 执行过程中的内存模型
  10. P95、P99.9百分位数值——服务响应时间的重要衡量指标