hdu--4081--次小生成树<Kruskal--cool>

我记得 大概是几个月前吧 那时候就看过 次小生成树了 虽然感觉听上去很简单 就是放条边进去 那条边出来 但实现起来不简单那=-=

这次 正好做到这题 是次小生成树的 就又去学了下...---传送

要是懒得点击链接 我把核心思想写下来.

一种容易想到的方法是枚举删除最小生成树上的边,再求最小生成树。用kruskal这种算法的复杂度为O(n*elog2e),当图比较稠密时,复杂度接近O(n^3)。

但有一种更简单的方法:先求最小生成树T,枚举添加不在T中的边,则添加后一定会形成环。找到环上边值第二大的边(即环中属于T中的最大边),把它删掉,计算当前生成树的权值,取所有枚举修改的生成树的最小值,即为次小生成树。

这种方法在实现时有更简单的方法:首先求最小生成树T,然后从每个结点u遍历最小生成树T,用一个二维数组max[u][v]记录结点u到结点v的路劲上 边的最大值(即最大边的值)。然后枚举不在T中的边(u,v),计算T- max[u][v] + w(u,v)的最小值,即为次小生成树的权值。显然,这种方法的时间复杂度为O(n^2 + e)。

见,第二种算法将原来的时间复杂度O(n^3)提高到了O(n^2)。

PS:对于这段话 我再补充一些我的个人想法 方便理解:

max[u][v]数组的值都是属于mst集合的边的权值

...你可以看到 这个图的mst的最小值是10--这边我假设我的mst是由A->B B->C C->D这3边构成

你可以看到 max[A][D]是5<在A->D的路径上有B->C==5,这里选取B->C是因为它是属于mst之中的>这里一定要知道我们在拿u结点进行遍历 对于任意max[u][v]出现过的值都是属于mst集合之中的值

然后我们进行操作 可以得到一个ans = mst - max[A][D] + e[A][D]这个 e[A][D]就是指AD这条边的权值 然后我们暂时记secondMst的值为10-5+6==11

然后我们继续操作 因为我们是进行O(m)的遍历 ,m是指图中所有的边

你可以看到 maax[B][D]是5 同样进行计算 mst - max[B][D] + e[B][D] 就是 10-5+5=10 小于刚刚得到的ans=11 所以 更新为10

然后 继续操作 发现最后一条边C->D 是属于mst集合之中的 就直接可以看做continue 然后因为遍历完成 就退出循环了

然后 比较 mst == secondMst 得出 该图有次小生成树

然后这题的话 是因为有个magic road的存在 使它可以用次小生成树来解决

前面的步骤处理 和上面差不多 因为代码实在是太长了 我也附加了一点注释

只是 当你处理到遍历所有边 来求ans的时候 注意下 如果这条边是属于mst之中与不属于mst之中的操作是不一样的

该边不属于mst

temp = ( peo[ tree[i].st ] + peo[ tree[i].end ] )*1.0 / ( mst - maxDist[ tree[i].st ][ tree[i].end ] );

除式的前面就是2个城市的人口 除式的后面-- 最小生成树的值 - 从st->end这条路径上所有出现的边中的最大值<将它设置为magic road>所以就减去它

该边属于mst

temp = ( peo[ tree[i].st ] + peo[ tree[i].end ] )*1.0 / ( mst - tree[i].dist );

除式前面同上  除式的后面--因为该边属于mst就直接减掉它

************************************************************

次小生成树 蛮不错的 理解了它 对于其它算法的理解与学习 也是有帮助的...就像我好像在前面博客说过的 可能你学习一段时间后 再去看前面的以前模棱两可的东西 会觉得清晰许多

  1 #include <iostream>
  2 #include <cstring>
  3 #include <queue>
  4 #include <algorithm>
  5 #include <iomanip>
  6 #include <cmath>
  7 using namespace std;
  8
  9 int cnt , num , n;
 10 const int size = 1010;
 11
 12 int x[size];
 13 int y[size];
 14 int peo[size];//记录每个城市的人数
 15 int father[size];
 16 double maxDist[size][size];//记录从i->j这条路径上的边的最大值
 17 struct Tree//将所有2个城市之间的信息存入这里 st与end存入的是在0-n的当中编号 这边相当于将(x,y)这个坐标以一个点来表示
 18 {
 19     int st;
 20     int end;
 21     double dist;
 22     bool flag;
 23 }tree[size*size];
 24 struct graph //最小生成树的结点
 25 {
 26     int to;
 27     int next;
 28     double dist;
 29 }edge[size*2];
 30 int head[size];
 31 struct data//求次小生成树过程中需要的结点信息
 32 {
 33     int id;//当前结点
 34     double maxDist;//从遍历点i到当前结点的最大边的距离
 35     data( int u , double v):id(u),maxDist(v){};
 36     data(){};
 37 };
 38 bool cmp( const Tree p , const Tree q )
 39 {
 40     return p.dist < q.dist;//按边的权值从小到大进行排序--这边就是2点之间的距离大小
 41 }
 42 void init( )
 43 {
 44     memset( father , -1 , sizeof(father) );
 45     memset( head , -1 , sizeof(head) );
 46 }
 47 int find( int x )
 48 {
 49     return father[x] == -1 ? x : father[x] = find( father[x] );
 50 }
 51 void add1( int from , int to , double dist )
 52 {
 53     edge[cnt].to = to;
 54     edge[cnt].dist = dist;
 55     edge[cnt].next = head[from];
 56     head[from] = cnt++;
 57 }
 58
 59 void add2( int st , int end , double dist )
 60 {
 61     tree[num].st = st;
 62     tree[num].end = end;
 63     tree[num].dist = dist;
 64     tree[num++].flag = false;
 65 }
 66
 67 double getDist( int p , int q )
 68 {
 69     return sqrt( ( (x[p]-x[q])*(x[p]-x[q]) + (y[p]-y[q])*(y[p]-y[q])*1.0 ) );
 70 }
 71
 72 double kruskal( )
 73 {
 74     init();
 75     int x , y;
 76     int edgeNum = 0;
 77     double ans = 0;
 78     sort( tree , tree+num , cmp );
 79     for( int i = 0 ; i<num ; i++ )//这里的i都是指第 I 条边
 80     {
 81         x = find( tree[i].st );
 82         y = find( tree[i].end );
 83         if(x!=y)//如果这条边的两个端点不属于一个连通块 就可以进行合并
 84         {
 85             edgeNum ++;
 86             add1( tree[i].st,tree[i].end,tree[i].dist );
 87             add1( tree[i].end,tree[i].st,tree[i].dist );
 88             tree[i].flag = true;//加入mst之中
 89             father[x] = y;
 90             ans += tree[i].dist;
 91         }
 92         if( edgeNum == n-1 )
 93             break;
 94     }
 95     return edgeNum == n-1 ? ans : -1;
 96 }
 97
 98 void bfs( int p )
 99 {
100     data now;
101     bool vis[size];
102     memset( vis , false , sizeof(vis) );
103     queue<data>q;
104     q.push( data(p,0) );
105     vis[p] = true;
106     while( !q.empty() )
107     {
108         now = q.front();
109         q.pop();
110         for( int i = head[now.id] ; i!=-1 ; i = edge[i].next )
111         {
112             int end = edge[i].to;
113             double dist = edge[i].dist;
114             if( !vis[end] )
115             {
116                 if( now.maxDist>dist )
117                     dist = now.maxDist;
118                 maxDist[p][end] = dist;
119                 vis[end] = true;
120                 q.push( data(end,dist) );
121             }
122         }
123     }
124 }
125
126 void secondMst( double mst )
127 {
128     double ans = -1;
129     for( int i = 0 ; i<n ; i++ )
130     {
131         bfs( i );
132     }
133     for( int i = 0 ; i<num ; i++ )//num遍历所有的边-尝试将该边设置为magic road--根据该边是否属于mst集合 进行不同操作
134     {
135         double temp;
136         if( !tree[i].flag )//该边不属于mst集合之中
137         {
138             temp = ( peo[ tree[i].st ] + peo[ tree[i].end ] )*1.0 / ( mst - maxDist[ tree[i].st ][ tree[i].end ] );
139         }
140         else
141         {
142             temp = ( peo[ tree[i].st ] + peo[ tree[i].end ] )*1.0 / ( mst - tree[i].dist );
143         }
144         ans = max( ans , temp );
145     }
146     cout<<setiosflags(ios::fixed);
147     cout<<setprecision(2)<<ans<<endl;
148 }
149
150 int main()
151 {
152     cin.sync_with_stdio(false);
153     int t;
154     cin >> t;
155     while( t-- )
156     {
157         num = cnt = 0;
158         cin >> n;
159         for( int i = 0 ; i<n ; i++ )
160         {
161             cin >> x[i] >> y[i] >> peo[i];
162         }
163         for( int i = 0 ; i<n ; i++ )
164         {
165             for( int j = 0 ; j<i ; j++ )
166             {
167                 double val = getDist(i,j);
168                 add2(i,j,val);
169             }
170         }
171         double mst = kruskal();
172         secondMst( mst );
173     }
174     return 0;
175 }

这里有个很让人抓狂的地方...用C++超时 G++AC 卧槽了.............

today:

  有jr发帖

  给在最好年纪陪伴你却最终没走到一起的女孩子留下一句话:<摘取一部分>

  多年后,你离了,我未娶,你和孩子我都要

  感谢那时你,温暖我横冲直撞的年纪。

  以前没钱,穷小子一个,你陪我吃了好久的路边摊。前几天和另一个女孩去吃,她说:多脏啊,女生不吃这个“的时候,才知道那些年多么珍贵

  从此我爱上的人,都像你。。。。。。。
  不要亮,也逛bxj

  

  求着要做你的备胎,不是非要在你身边。
  是我怕你找不到那样一个你想要的能在精神和物质上都给你满足的他时,
  我能,给你煮泡面,为你洗衣服,攒很久的钱为你买瓶DHC,为你淘双新百伦。。

  你说的,每个女孩都希望有个好老公,你不过很普通而已。
  你说,你太自私,但是你爱我。
  你说,我不懂圆滑,爱得罪人,出力不讨好,在社会上吃不开。
  你说,你想在北京,有房有车,生活殷实,工作清闲。
  你说你会爱你的家人。

  谢谢你在最纯真年代的陪伴;
  谢谢我在最好的年华的抛弃;
  谢谢你再三犹豫后无法和我面对最难的人生。

  还是希望你能找到你的生活。希望你一直过的比我好。

  你不想来我家乡,我就过去呗;你不喜欢我不会喝酒,我就逼自己去喝;你不喜欢我哪里,我都改,好不好.....我只是很想很想和你在一起。工作了,分手 了,终于有一晚喝多了,忍不住给你打了电话,哭喊了一晚上的名字,最后你还是不言不语。你该了解我的,我有多倔强,甚至连家里人都不允许说你一句坏话,甚 至妈妈担心的对我说出以后你们离这么远,分手怎么办,我都会很生气说不要说....我只是想起你的时候还是很痛,爱到最后,只有放不开的犯贱,从来都没有 因为感动而回来的爱人。 说来很搞笑,前两天陪暧昧对象去看《闺蜜》,看到希汶最后找林杰说的那段话:你不想这么早结婚,我们就不要这么早结婚嘛;你不想去巴黎度蜜月,我们就不去 巴黎度蜜月啊;你想去哪里我都陪你去。好不好。我都改嘛,好不好.....看到这一段,想到自己,竟然不能自已,一个大老爷们在电影院为一部女生电影泣不 成声。 顺便说一句,在你之后,再也不能像以前对你一样,那么心甘命抵的去爱一个人,再也回不去了。祝君安好~

  “你永远是我爱得最纯粹最深刻的人。”

hdu--4081--次小生成树<Kruskal--cool>,布布扣,bubuko.com

时间: 2024-10-12 04:48:11

hdu--4081--次小生成树<Kruskal--cool>的相关文章

hdu 4081 次小生成树

简单说下思想(这里引用自http://blog.csdn.net/jarily/article/details/8883858) /* *算法引入: *设G=(V,E,w)是连通的无向图,T是图G的一棵最小生成树; *如果有另一棵树T1,满足不存在树T',ω(T')<ω(T1),则称T1是图G的次小生成树; * *算法思想: *邻集的概念:由T进行一次可行交换得到的新的生成树所组成的集合,称为树T的邻集,记为N(T); *设T是图G的最小生成树,如果T1满足ω(T1)=min{ω(T')|T'∈

POJ 1679:The Unique MST(次小生成树&amp;&amp;Kruskal)

The Unique MST Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 19941   Accepted: 6999 Description Given a connected undirected graph, tell if its minimum spanning tree is unique. Definition 1 (Spanning Tree): Consider a connected, undire

UVA 10462 Is There A Second Way Left? (次小生成树+kruskal)

题目大意: Nasa应邻居们的要求,决定用一个网络把大家链接在一起.给出v个点,e条可行路线,每条路线分别是x连接到y需要花费w. 1:如果不存在最小生成树,输出“No way”. 2:如果不存在次小生成树,输出“No second way”. 3:如果两者都存在,输出次小生成树的长度. 解题思路: 次小生成数+kruskal模板 1 #include <cmath> 2 #include <queue> 3 #include <string> 4 #include &

Constructing Roads-最小生成树(kruskal)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1102 题目描述: 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 6 struct node 7 { 8 int u,v,cost; 9 }a[10005]; 10 int pre[105]; 11 int fin(int x) 12 { 13 if(

HDU 4081 Qin Shi Huang&#39;s National Road System 次小生成树变种

Qin Shi Huang's National Road System Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) [Problem Description] During the Warring States Period of ancient China(476 BC to 221 BC), there were seven kingdoms in China ---

HDU 4081 Qin Shi Huang&#39;s National Road System(最小生成树/次小生成树)

题目链接:传送门 题意: 有n坐城市,知道每坐城市的坐标和人口.现在要在所有城市之间修路,保证每个城市都能相连,并且保证A/B 最大,所有路径的花费和最小,A是某条路i两端城市人口的和,B表示除路i以外所有路的花费的和(路径i的花费为0). 分析: 先求一棵最小生成树,然后枚举每一条最小生成树上的边,删掉后变成两个生成树,然后找两个集合中点权最大的两 个连接起来.这两个点中必然有权值最大的那个点,所以直接从权值最大的点开始dfs. 为了使A/B的值最大,则A尽可能大,B尽可能小.所以B中的边一定

hdu 4081 Qin Shi Huang&#39;s National Road System 次小生成树 算法

Qin Shi Huang's National Road System Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 4180    Accepted Submission(s): 1450 Problem Description During the Warring States Period of ancient China(4

HDU 4081—— Qin Shi Huang&#39;s National Road System——————【次小生成树、prim】

Qin Shi Huang's National Road System Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 5608    Accepted Submission(s): 1972 Problem Description During the Warring States Period of ancient China(47

hdu 4081 Qin Shi Huang&#39;s National Road System 树的基本性质 or 次小生成树

During the Warring States Period of ancient China(476 BC to 221 BC), there were seven kingdoms in China ---- they were Qi, Chu, Yan, Han, Zhao, Wei and Qin. Ying Zheng was the king of the kingdom Qin. Through 9 years of wars, he finally conquered all

hdu 4081 Qin Shi Huang&#39;s National Road System (次小生成树)

Qin Shi Huang's National Road System Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 3843    Accepted Submission(s): 1336 Problem Description During the Warring States Period of ancient China(47