POJ 1251 (最小生成树)
2016-03-16 10:30
246 查看
很明显,这是一道 最小生成树的例子。也就是,从图中选取若干条边将所有顶点连接起来,并且所选取的这些边的权值之和最小。
算法:Prim算法,或者 Kruskal算法
Prim算法: 首先选择一个点为起点,然后找到与该边相邻权值最小的边,选中该边上的另一个点,然后选择 与选中点 相连接的最小边,这样循环下去,直到包含所有节点
用d[i]表示 与 i 点相邻的最短边的权值,这点是与 Dijkstra算法唯一的不同点
#include <iostream>
using namespace std;
#define MAXV 30
#define MAX 1<<29
int n;
int map[MAXV][MAXV];
int d[MAXV];
bool vis[MAXV];
void prim(){
int i,j;
int k = 0;
for(i=0;i<n;i++){
vis[i] = 0;
d[i] = map[0][i];
}
for(i=1;i<=n;i++){
int temp = MAX;
for(j=0;j<n;j++){
if(!vis[j]&&d[j]<temp){
temp = d[j];
k = j;
}
}
vis[k] = 1;
for(j=0;j<n;j++){
if(!vis[j]&&d[j]>map[k][j])
d[j] = map[k][j];
}
}
for(i=0;i<n;i++)
d[0] += d[i];
cout<<d[0]<<endl;
}
int main(){
int i,j,num,weight;
char a[2],b[2];
while(cin>>n,n){
for(i=0;i<=n;i++)
for(j=0;j<=n;j++)
if(i == j)
map[i][j] = 0;
else
map[i][j] = MAX;
for(i=1;i<n;i++){
cin>>a>>num;
for(j=1;j<=num;j++){
cin>>b>>weight;
map[a[0]-'A'][b[0]-'A'] = map[b[0]-'A'][a[0]-'A'] = weight;
}
}
prim();
}
return 0;
}
Kruskal算法是另一种求解最小生成树的经典解法
算法思想:
不断地选择图中权值最小的边,前提是 不能构成回路。
#include <iostream>
#include <algorithm>
using namespace std;
#define INF 1<<29
int p[27];
struct pro{
int u;
int v;
int w;
}map[80];
bool cmp(pro a,pro b){
return a.w<b.w;
}
int find(int a){
return a == p[a]?a:a=find(p[a]);
}
int main(){
int n;
int i,j,num,c;
char a[2],b[2];
while(cin>>n,n){
int k = 0;
for(i=0;i<27;i++)
p[i] = i;
for(i=0;i<n-1;i++){
cin>>a>>num;
for(j=1;j<=num;j++,k++){
cin>>b>>c;
map[k].u = a[0] - 'A';
map[k].v = b[0] - 'A';
map[k].w = c;
}
}
sort(map,map+k,cmp);
int ans = 0;
for(i=0;i<k;i++){
int x = find(map[i].u);
int y = find(map[i].v);
if(x!=y){
ans += map[i].w;
p[x] = y;
}
}
cout<<ans<<endl;
}
return 0;
}
这个算法 关键是 如何判断 是否有环,方法是 利用 并查集。
总结:Prim算法更注重 点的关系;而Kruskal算法更注重 边的关系
算法:Prim算法,或者 Kruskal算法
Prim算法: 首先选择一个点为起点,然后找到与该边相邻权值最小的边,选中该边上的另一个点,然后选择 与选中点 相连接的最小边,这样循环下去,直到包含所有节点
用d[i]表示 与 i 点相邻的最短边的权值,这点是与 Dijkstra算法唯一的不同点
#include <iostream>
using namespace std;
#define MAXV 30
#define MAX 1<<29
int n;
int map[MAXV][MAXV];
int d[MAXV];
bool vis[MAXV];
void prim(){
int i,j;
int k = 0;
for(i=0;i<n;i++){
vis[i] = 0;
d[i] = map[0][i];
}
for(i=1;i<=n;i++){
int temp = MAX;
for(j=0;j<n;j++){
if(!vis[j]&&d[j]<temp){
temp = d[j];
k = j;
}
}
vis[k] = 1;
for(j=0;j<n;j++){
if(!vis[j]&&d[j]>map[k][j])
d[j] = map[k][j];
}
}
for(i=0;i<n;i++)
d[0] += d[i];
cout<<d[0]<<endl;
}
int main(){
int i,j,num,weight;
char a[2],b[2];
while(cin>>n,n){
for(i=0;i<=n;i++)
for(j=0;j<=n;j++)
if(i == j)
map[i][j] = 0;
else
map[i][j] = MAX;
for(i=1;i<n;i++){
cin>>a>>num;
for(j=1;j<=num;j++){
cin>>b>>weight;
map[a[0]-'A'][b[0]-'A'] = map[b[0]-'A'][a[0]-'A'] = weight;
}
}
prim();
}
return 0;
}
Kruskal算法是另一种求解最小生成树的经典解法
算法思想:
不断地选择图中权值最小的边,前提是 不能构成回路。
#include <iostream>
#include <algorithm>
using namespace std;
#define INF 1<<29
int p[27];
struct pro{
int u;
int v;
int w;
}map[80];
bool cmp(pro a,pro b){
return a.w<b.w;
}
int find(int a){
return a == p[a]?a:a=find(p[a]);
}
int main(){
int n;
int i,j,num,c;
char a[2],b[2];
while(cin>>n,n){
int k = 0;
for(i=0;i<27;i++)
p[i] = i;
for(i=0;i<n-1;i++){
cin>>a>>num;
for(j=1;j<=num;j++,k++){
cin>>b>>c;
map[k].u = a[0] - 'A';
map[k].v = b[0] - 'A';
map[k].w = c;
}
}
sort(map,map+k,cmp);
int ans = 0;
for(i=0;i<k;i++){
int x = find(map[i].u);
int y = find(map[i].v);
if(x!=y){
ans += map[i].w;
p[x] = y;
}
}
cout<<ans<<endl;
}
return 0;
}
这个算法 关键是 如何判断 是否有环,方法是 利用 并查集。
总结:Prim算法更注重 点的关系;而Kruskal算法更注重 边的关系
相关文章推荐
- 3.14项目管理一般知识和立项管理作业
- CoreData的增删改查
- 发现大量的TIME_WAIT解决办法
- 蓝桥杯 密码发生器
- python学习笔记(6)-高级特性(二)-迭代
- Java Web Session 登录实例
- 字符设备驱动
- 自动化测试:k8s环境下,通过检测文件是否存在来自动启停tomcatapp的方法_20160316_七侠镇莫尛貝
- 工作感悟-2014.6.28
- 激活BI Content
- 对前两次实验的总结与对第三次实验的展望
- 程序员常用工具
- 堆与栈 浅析
- Jira平台数据自动化获取(二)--JQL语句
- 编外话15
- hadoop 集群开启之后datanode没有启动
- java类库中的File类使用
- 仿MIUI的Toast动画效果实现
- AlphaGo关键技术,Deep Learning(深度学习)<1>
- JAVA Web防止表单重复提交实例