yuanyuelang
导航
C++博客
首页
新随笔
联系
聚合
管理
<
2024年11月
>
日
一
二
三
四
五
六
27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
1
2
3
4
5
6
7
留言簿
给我留言
查看公开留言
查看私人留言
随笔分类
编程之美
(rss)
编程珠玑
(rss)
文章分类
计算几何学
(rss)
数据结构(1)
(rss)
数论(4)
(rss)
图论(4)
(rss)
转载(1)
(rss)
文章档案
2010年4月 (1)
2009年9月 (9)
阅读排行榜
评论排行榜
常用链接
我的随笔
我的评论
我参与的随笔
统计
随笔 - 0
文章 - 10
评论 - 5
引用 - 0
最新评论
1. re: 数论(2)-------扩展欧几里得算法
定理:gcd(a,b) = gcd(b,a mod b) (a>b 且a mod b 不为0)
--s
2. re: 数论(2)-------扩展欧几里得算法
min=y-[y/a]y错了.
--CrazyForAC
3. re: 数论(2)-------扩展欧几里得算法
评论内容较长,点击标题查看
--晓楠
4. re: 数论(2)-------扩展欧几里得算法
顶
--ding
5. re: 不相交集合数据结构[未登录]
太简陋了一点吧
--a
最小生成树之Kruskal算法
最小生成树是图论的一个重要部分,解决这个问题的算法主要有Kruskal算法和Prim算法。
最小生成树:顾名思义是一棵树,该树是图中权值和最小的。
我们先来介绍Kruskal算法,Prim算法请参阅
最小生成树之Prim算法
该算法的基本思路:贪心,如何贪心呢?
它的贪心准则是:
1.每次从剩下的边中选择一个不会产生环路而且权值最小的边加入到已经选择好的边的集合中。
2.它需要e步的操作,e表示图的边数,我们可以按权值排好序后,对每一条边进行选择,如果加入到已经选择好的边中会产生回路的现象,就不要了。。。否则加入到已经选择好的边中。
3.我们还需用到并查集的思想,有关并查集的介绍,请查看我的另一篇博文
不相交集合数据结构
4.复杂度:O(ElgE),其中E为图的边数
接下来我们引用POJ上的一个经典题目来分析,题目网址
http://acm.pku.edu.cn/JudgeOnline/problem?id=1861
题目大意是:题目给出的是图的顶点和所有边的集合,要求输出的是最小生成树的边
我们来看下源码啦:
#include
<
iostream
>
using
namespace
std;
#include
<
algorithm
>
#include
<
memory.h
>
#define
MAXEDGE 15001
//
最大边数
#define
MAXNODE 1001
//
最大节点数
int
p[MAXNODE],rank[MAXNODE];
//
用于不相交集合
int
start[MAXEDGE],end[MAXEDGE],weight[MAXEDGE],VNum,ENum;
//
分别为边的起点,终点,权重,节点数和边数
int
result_s[MAXEDGE],result_e[MAXEDGE];
//
分别为存储最小生成树的起点,终点
int
max_weight,id[MAXEDGE];
void
make_set(
int
x)
{
p[x]
=
x;
rank[x]
=
0
;
}
int
find_set(
int
x)
{
if
(p[x]
!=
x)
p[x]
=
find_set(p[x]);
return
p[x];
}
void
Union(
int
x,
int
y)
{
x
=
find_set(x);
y
=
find_set(y);
if
(rank[x]
>
rank[y])
p[y]
=
x;
else
if
(rank[x]
<
rank[y])
p[x]
=
y;
else
if
(rank[x]
==
rank[y])
{
p[x]
=
y;
rank[y]
++
;
}
}
bool
cmp(
int
i,
int
j)
//
用于sort函数
{
return
weight[i]
<
weight[j];
}
void
Kruskal()
{
int
i,min,index
=
0
,count
=
0
,k
=
0
;
max_weight
=
0
;
for
(i
=
1
;i
<=
VNum;i
++
)
make_set(i);
sort(id,id
+
ENum,cmp);
//
对所有边进行排序,注意id数组的妙用
while
(
true
)
{
min
=
id[index
++
];
if
(find_set(start[min])
!=
find_set(end[min]))
{
//
对每条边进行处理,如果起点和终点不在同一集合合并之
Union(start[min],end[min]);
result_s[k]
=
start[min];
//
保存结果
result_e[k
++
]
=
end[min];
count
++
;
if
(max_weight
<
weight[min])
max_weight
=
weight[min];
}
if
(count
==
VNum
-
1
)
break
;
//
当边数等于节点数-1的时候表示已经完成
}
}
int
main()
{
int
i;
cin
>>
VNum
>>
ENum;
for
(i
=
0
;i
<
ENum;i
++
)
{
cin
>>
start[i]
>>
end[i]
>>
weight[i];
id[i]
=
i;
}
Kruskal();
cout
<<
max_weight
<<
endl
<<
VNum
-
1
<<
endl;
for
(i
=
0
;i
<
VNum
-
1
;i
++
)
cout
<<
result_s[i]
<<
"
"
<<
result_e[i]
<<
endl;
return
0
;
}
posted on 2009-09-13 21:18
原语饿狼
阅读(685)
评论(0)
编辑
收藏
引用
所属分类:
图论
只有注册用户
登录
后才能发表评论。
【推荐】100%开源!大型工业跨平台软件C++源码提供,建模,组态!
相关文章:
每对顶点间的最短路径之Floyd-Warshall算法
单源最短路径之Dijkstra算法
最小生成树之Prim算法
最小生成树之Kruskal算法
网站导航:
博客园
IT新闻
BlogJava
知识库
博问
管理
Powered by:
C++博客
Copyright © 原语饿狼