【有重边与无重边的无向图的割边求法】

无向图无重边:也就每两个顶点之间最多有一条边相连【也就是根据顶点编号即可确定边】【如下】

无向图有重边如:顶点1与顶点2有两条或更多的边直接相连【也就是不能根据顶点编号来确定边】【如下】

首先介绍无重边的无向图的割边求法:由于无重边的无向图中可以根据顶点来确定边,所以函数中的参数 u 和 fa  都是顶点。

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <vector>
 4 using namespace std;
 5 const int N = 1000 + 10;
 6 vector<int> g[N];
 7 int dfs_clock,pre[N];
 8 int cnt;
 9 int dfs(int u, int fa)
10 {
11     int lowu = pre[u] = ++dfs_clock;
12     int i,v,lowv;
13     for(i=0; i<g[u].size(); ++i)
14     {
15         v = g[u][i];
16         if(!pre[v])
17         {
18             lowv = dfs(v,u);
19             lowu = min(lowu,lowv);
20             if(lowv > pre[u])//相对于割点,只把等号给去掉了
21                 cnt++;
22         }
23         else if(v!=fa && pre[v]<lowu)//v!=fa 因为无重边,所以由v != fa来防止一条边的端点反复使用两次,从而避免使原本是桥的边判定为了不是桥,但也正因为它不更新父节点导致了其不能处理重边
24             lowu = pre[v];
25     }
26     return lowu;
27 }
28 int main()
29 {
30     int i,x,y;
31     int n,m;
32     scanf("%d%d",&n,&m);
33     for(i=0; i<m; ++i)
34     {
35         scanf("%d%d",&x,&y);
36         g[x].push_back(y);
37         g[y].push_back(x);
38     }
39     dfs(1,-1);
40
41     printf("%d\n",cnt);
42 }

下面是有重边的无向图的割边求法:由于有重边的无向图中不可以根据顶点来确定边,所以函数中的参数 u 是顶点,而 id 是边的编号。

 1 #include"string.h"
 2 #include"stdio.h"
 3 #include"iostream"
 4 #define M 1111
 5 #define inf 999999999
 6 using namespace std;
 7 struct st
 8 {
 9     int u,v,w,next;
10 }edge[M*M*2];
11 int head[M],dfn[M],low[M],bridge[M],n,t,index,num,mini,flag;
12 void init()
13 {
14     t=0;
15     memset(head,-1,sizeof(head));
16 }
17 void add(int u,int v,int w)
18 {
19     edge[t].u=u;
20     edge[t].v=v;
21     edge[t].w=w;
22     edge[t].next=head[u];
23     head[u]=t++;
24 }
25 void tarjan(int u,int id)
26 {
27     dfn[u]=low[u]=++index;
28     int i;
29     for(i=head[u];i!=-1;i=edge[i].next)
30     {
31         if(i==(1^id))continue; //和无重边的无向图通过v!=fa来避免同一条边重复遍历的处理方式不一样,这个是利用一条边的编号的异或关系来避免重复遍历的
32         int v=edge[i].v;
33         if(!dfn[v])
34         {
35             tarjan(v,i);
36             low[u]=min(low[u],low[v]);
37             if(low[v]>dfn[u])
38             {
39                 bridge[num++]=i;
40                 if(mini>edge[i].w)
41                     mini=edge[i].w;
42             }
43
44         }
45         low[u]=min(low[u],dfn[v]);  //由于上面已经对同一条边进行规避了,所以不需要使用多余的判断,直接就能更新了
46     }
47 }
48 void solve()
49 {
50     index=num=flag=0;
51     memset(dfn,0,sizeof(dfn));
52     memset(low,0,sizeof(low));
53     for(int i=1;i<=n;i++)
54     {
55         if(!dfn[i])
56         {
57             flag++;
58             tarjan(i,-1);
59         }
60
61     }
62 }
63 int main()
64 {
65     int m;
66     while(scanf("%d%d",&n,&m),m||n)
67     {
68         init();
69         while(m--)
70         {
71             int a,b,c;
72             scanf("%d%d%d",&a,&b,&c);
73             add(a,b,c);
74             add(b,a,c);
75         }
76         mini=inf;
77         solve();
78         if(flag>1)
79             printf("0\n");
80         else if(num==0)
81             printf("-1\n");
82         else
83         {
84             if(mini==0)
85                 printf("1\n");
86             else
87                 printf("%d\n",mini);
88         }
89     }
90 }  

原文地址:https://www.cnblogs.com/MekakuCityActor/p/9033586.html

时间: 2024-08-02 08:04:47

【有重边与无重边的无向图的割边求法】的相关文章

POJ 3352 &amp; 3177 无向图的边-双连通分量(无重边 &amp; 重边)

无向图的边-双连通分量 无向图的双连通分量实际上包含两个内容:点-双连通分量.边-双连通分量 点-双连通分量是指:在该连通分量里面,任意两个点之间有多条点不重复的路径(不包括起点.终点) 边-双连通分量是指:在该连通分量里面,任意两个点之间有多条边不重复的路径 在求解点-双连通分量时,无向图有没有重边都没有关系,因为一个点只能经过一次(有重边也无妨) 该篇文章并不深入讨论点-双连通分量,给出代码给有兴趣的参考参考:(也可以看看POJ2942这道题, 解题报告) /*===============

ZOJ 2588 Burning Bridges(无向图求割边)

ZOJ 2588 Burning Bridges 链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2588 题意:给定一个无向图连通图,(其中可能有重边),要求去掉一条边之后,使得整个图不再连通.输出这些符合条件的边的序号. 思路:这就是一个简单的无向图求割边,需要注意的是这个无向图有重边,重边一定不是割边. 代码: /*========================================= 无向图求割点

连通性2 无向图的割边 (cut edge)

这是DFS系列的第二篇 割边的概念 In graph theory, a bridge, isthmus, cut-edge, or cut arc is an edgeof a graph whose deletion increases its number of connected components. Equivalently, an edge is a bridge if and only if it is not contained in any cycle. A graph is

zoj2588(连通分量,求解无向图的割边)

B - Burning Bridges Time Limit:5000MS     Memory Limit:32768KB     64bit IO Format:%lld & %llu Submit Status Description Ferry Kingdom is a nice little country located on N islands that are connected by M bridges. All bridges are very beautiful and a

无重边无向连通图的割点和桥

1 #include<cstdio> 2 #include<cstring> 3 #include<vector> 4 #include<algorithm> 5 using namespace std; 6 vector<vector<int> > g; 7 int dfn[11000];//节点在dfs过程中的访问序号(也可以叫做开始时间) 8 int low[11000];//节点的子树中能够通过非父子边追溯到的最早的节点的df

无重边有向连通图的强连通分量

1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<vector> 5 #include<stack> 6 using namespace std; 7 int n,m,ntime;//ntime记录dfs访问时间 8 int instack[11000];//标记点是否在栈中 9 int dfn[11000];//节点在dfs过程中的访问序号(也可以叫做

zoj2588(无向图求割边)

这道题其实就是一道很简单的割边的模板题,不过需要处理重边导师意见有点麻烦的事 #include <iostream> #include <stdio.h> #include <string.h> #include <algorithm> using namespace std; const int MAXN=20005; const int MAXM=200005; struct edge { int to,next,id,num;//这个地方需要在原有模板

HDU 3849 无向图的割边

By Recognizing These Guys, We Find Social Networks Useful Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 125536/65536 K (Java/Others)Total Submission(s): 2319    Accepted Submission(s): 603 Problem Description Social Network is popular these

ZOJ2588.Burning Bridges——边双连通分量,有重边

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1588 题目描述: Ferry 王国是一个漂亮的岛国,一共有N 个岛国.M 座桥,通过这些桥可以从每个小岛都能到达任何一个小岛.很不幸的是,最近Ferry 王国被Jordan 征服了.Jordan 决定烧毁所有的桥.这是个残酷的决定,但是Jordan 的谋士建议他不要这样做,因为如果烧毁所有的桥梁,他自己的军队也不能从一个岛到达另一个岛.因此Jordan 决定烧尽可能多的桥,只