hdu Caocao's Bridges(无向图边双连通分量,找出权值最小的桥)

简介:
 1 /*
 2     题意:给出一个无向图,去掉一条权值最小边,使这个无向图不再连同!
 3     
 4     tm太坑了...
 5     1,如果这个无向图开始就是一个非连通图,直接输出0
 6     2,重边(两个节点存在多条边, 权值不一样)
 7     3,如果找到了桥的最小权值为0,也就是桥上的士兵数为0,那么还是要最少派一个
 8     士兵过去炸掉桥! 
 9     
10     思路:假设每两个节点最多只有一条边进行相连!
11     进行tarjan算法,如果该算法调用了超过2次,说明这个原图就是不连通的!
12     否则在tarjan算法中将桥存起来!然后我们遍历每一座桥,看一看我们找到的
13     桥(连接的两个定点分别是u, v)是不是(u, v)只有一条路相连接,如果是的,
14     那么就跟新最小值! 
15 */
16 #include<iostream>
17 #include<cstdio>
18 #include<cstring>
19 #include<algorithm>
20 #define M 1000005
21 #define INF 0x3f3f3f3f
22 #define N 1005
23 using namespace std;
24 struct EDGE{
25    int u, v, w, nt; 
26    EDGE(){}
27    EDGE(int u, int v, int w, int nt){
28        this->u=u;
29        this->v=v;
30        this->w=w;
31        this->nt=nt;         
32    }
33 };
34 
35 EDGE edge[M];
36 EDGE brige[M];
37 int first[N];
38 int low[N], pre[N];
39 int dfs_clock;
40 int n, m, cnt, ret;
41 
42 
43 void tarjan(int u, int fa){
44     low[u]=pre[u]=++dfs_clock;
45     for(int e=first[u]; e!=-1; e=edge[e].nt){
46          int v=edge[e].v;
47         
48          if(!pre[v]){
49               tarjan(v, u);
50               low[u]=min(low[u], low[v]);
51               if(low[v]>pre[u])
52                  brige[ret++]=edge[e];
53          }         
54          else if(v!=fa && pre[u]>pre[v])
55               low[u]=min(low[u], pre[v]);
56     }        
57 }
58 
59 int main(){
60     while(scanf("%d%d", &n, &m) && (n||m)){
61         memset(first, -1, sizeof(first));
62         cnt=0;
63         while(m--){
64             int u, v, w;
65             scanf("%d%d%d", &u, &v, &w);
66             edge[cnt]=EDGE(u, v, w, first[u]);
67             first[u]=cnt++;
68             edge[cnt]=EDGE(v, u, w, first[v]);
69             first[v]=cnt++;
70         }      
71         dfs_clock=0;
72         ret=0;
73         memset(low, 0, sizeof(low));
74         memset(pre, 0, sizeof(pre)); 
75         int flag=0;
76         for(int i=1; i<=n; ++i)
77            if(!pre[i]){
78               ++flag;
79               if(flag==2) break;
80               tarjan(i, -1);
81            }
82         
83         int minNum=INF;
84         if(flag==2) minNum=0;
85         else{
86            for(int i=0; i<ret; ++i)
87              if(brige[i].w<minNum){//对假定的桥判断 
88                 int cc=0;
89                 for(int e=first[brige[i].u]; e!=-1; e=edge[e].nt)
90                    if(edge[e].v==brige[i].v) ++cc;
91                 if(cc==1)  minNum=brige[i].w;//说明是真正的桥 
92              }
93            if(minNum==INF) minNum=-1;
94            else if(minNum==0) minNum=1;//这一句不要忘记了! 
95         }
96         printf("%d\n", minNum);
97     } 
98     return 0;    
99 }
复制代码

 










本文转自 小眼儿 博客园博客,原文链接:http://www.cnblogs.com/hujunzheng/p/3937412.html,如需转载请自行联系原作者
目录
相关文章
|
1月前
|
人工智能 算法 BI
【深度优先搜索 图论 树】2872. 可以被 K 整除连通块的最大数目
【深度优先搜索 图论 树】2872. 可以被 K 整除连通块的最大数目
|
10月前
UVa10075 - Airlines(所有点对之间的最短距离)
UVa10075 - Airlines(所有点对之间的最短距离)
23 0
|
机器学习/深度学习 存储 算法
1065: 无向图的连通分量计算
1065: 无向图的连通分量计算
88 0
|
存储 算法 C语言
6-1 最小生成树(普里姆算法) (10分)
6-1 最小生成树(普里姆算法) (10分)
6-1 最小生成树(普里姆算法) (10分)
|
人工智能 Prometheus Cloud Native
牛客第五场 B Graph最小异或生成树
这道题涉及到最小异或生成树,要理解这个首先要明白 01字典树 关于01字典树呢,先来一道板子题hdu4825 ==》 不方便跳转的同学们可以看下面的题 Problem Description Zeus 和 Prometheus 做了一个游戏,Prometheus 给 Zeus 一个集合,集合中包含了N个正整数,随后 Prometheus 将向 Zeus 发起M次询问,每次询问中包含一个正整数 S ,之后 Zeus 需要在集合当中找出一个正整数 K ,使得 K 与 S 的异或结果最大。Prometheus 为了让 Zeus 看到人类的伟大,随即同意 Zeus 可以向人类求助。
109 0
牛客第五场 B Graph最小异或生成树
|
Go
[Nowcoder / POJ2728] 最优比率生成树 | 二分 + prim
有n个点,其中,每个点给出位置坐标( x , y ) 以及高度z ,两点之间的距离为两点之间的欧几里得距离 两点之间建立一条路的代价为两点之间的高度差,问将n 个点联通的情况下,求出最大的cost/dis
112 0
|
算法
图的最小生成树——Prim算法
Prim算法思想如下:首先将图的点分为两部分,一种是访问过的u,一种是没有访问过的v1:首先在访问过的顶点中找一条到u到v的一条权值最小的边2:然后将这条边中的v中的顶点添加到u中,直到边的个数=顶点数-1如下图所示,下面是prim算法的图示(原图)(a -1)(a -2)(a -3)(a -4) (a -5) (a -6) 算法的流程图如下: 代码如下:// // main.
7958 0
|
算法
图的最小生成树——Kruskal算法
Kruskal算法的思想如下 假设有n个顶点的连通图。首先先构造有顶点构成的集合0,每个顶点都是一个集合,不含有任何边。 在边找一个最小权值的边 判断这个边的俩个顶点是否来自于两个不同的集合,若是就将它俩归并为一个集合,然后将这个边添加到要构成的图的集合中。
5201 0