您的位置:首页 > 其它

最小生成树--算法案列(poj1251)

2017-11-22 20:50 316 查看


Lagrishan的一个热带岛屿上的行政长官有一个问题要解决。他决定把几年前得到的外国援助资金用于修建村庄之间的道路。但是丛林比道路多太多了,使道路网络的维护太过于昂贵了。理事会必须选择停止维修一些道路。上述左侧图显示当前所有使用中的道路,以及现在每月的维护费用。当然,村庄之间必需有一些公路能够相通,即使路线并不像以前一样短。行政长官想告诉理事会怎样才使每月的花费最小,并且所维持的道路,将连接所有村庄。上面的地图标记了村庄A到I。右边的图显示了每月能够维护道路的最小费用为216aacms。你的任务是编写一个程序,将解决这些问题。 

输入: 

输入包含的数据集个数在100以内,以0作为最后一行。每个数据集的第一行只包含一个表示村庄个数的数n,1<n<27,并且这n个村庄是由大写字母表里的前n个字母表示。接下来的n-
1行是由字母表的前n-1个字母开头。最后一个村庄表示的字母不用输入。对于每一行,以每个村庄表示的字母开头,然后后面跟着一个数字,表示有多少条道路可以从这个村到后面字母表中的村庄。如果k是大于0,表示该行后面会表示k条道路的k个数据。每条道路的数据是由表示连接到另一端村庄的字母和每月维修该道路的花费组成。维修费用是正整数的并且小于100。该行的所有数据字段分隔单一空白。该公路网将始终连接所有的村庄。该公路网将永远不会超过75条道路。没有任何一个村庄会有超过15条的道路连接到其他村庄(之前或之后的字母)。

在下面的示例输入,其中第一个数据集是与上面的地图相一致的。 

Sample Input

9

A 2 B 12 I 25

B 3 C 10 H 40 I 8

C 2 D 18 G 55

D 1 E 44

E 2 F 60 G 38

F 0

G 1 H 35

H 1 I 35

3

A 2 B 10 C 40

B 1 C 20

0

Sample Output

216

30

主要是怎么去最小生成树;这里用的是克鲁斯卡尔算法;

可以去百度下一这个算法,就知道是怎么的一个算法;

#include <iostream>
#include <cstring>
#define NUM 30

using namespace std;
int N;//表示村庄数;
int Graph[NUM][NUM];

int k_road()
{
int min_totle_free = 0;
int set[NUM];
for(int i = 1;i<=N;i++)
set[i] = i;//初始化set数组;
int k = 1;
int a = 1;
int b = 1;
int min_value = 1<<30;
int min_free;
while(k<=N-1){
for(int i = 1;i<=N;i++)
for(int j = i+1;j<=N;j++){
if(Graph[i][j]<min_value){
min_value = Graph[i][j];
a = i;
b = j;
}
}//找到权值最小的值;
min_free = min_value;
min_value = Graph[a][b] = 1<<30;
if(set[a]!=set[b]){
min_totle_free+=min_free;
k++;
int temp = set[b];
for(int i = 1;i<=N;i++)
if(set[i]==temp)
set[i] = set[a];
}
}
return min_totle_free;
}

int main()
{
while(cin>>N&&N!=0){
memset(Graph,125,sizeof(Graph));
for(int i = 1;i<N;i++){
char temp1;//表示每一行;
int totle;
cin>>temp1>>totle;
int x = temp1-'A'+1;
for(int i = 1;i<=totle;i++){
char temp2;
int value;
cin>>temp2>>value;
int y = temp2-'A'+1;
Graph[x][y]=value;
}
}//构造图成功;
//        for(int i = 1;i<=N;i++){
//            for(int j = 1;j<=N;j++)
//                cout <<Graph[i][j]<<" ";
//            cout <<endl;
//        }

//        用克鲁斯卡尔算法
cout << k_road()<<endl;;
}
return 0;
}


//另一种算法:普利姆算法

#include <iostream>
#include <cstring>
#define NUM 30

using namespace std;
int N;//表示村庄数;
int Graph[NUM][NUM];

//普利姆算法

struct VNode
{
int xu_hao;
int value;
}minside[NUM];

int min_xu()
{
int i = 1;
while(!minside[i].value&&i<=N)
i++;
int k = i;
int min_v = minside[k].value;
for(int j = 1;j<=N;j++)
if(minside[j].value<min_v&&minside[j].value>0)
{min_v = minside[j].value;k = j;}
return k;
}

int pu_G()
{
for(int i =0;i<NUM;i++)
{minside[i].value = 0;minside[i].xu_hao = 0;}

int min_totle_value = 0;
for(int i = 1;i<=N;i++){
minside[i].xu_hao = 1;
minside[i].value = Graph[1][i];
}
minside[1].value = 0;
for(int i = 1;i<N;i++){
int k = min_xu();
min_totle_value+=minside[k].value;
minside[k].value = 0;
for(int i = 1;i<=N;i++)
if(minside[i].value>Graph[k][i]){
minside[i].xu_hao = k;
minside[i].value = Graph[k][i];
}
}
return min_totle_value;
}

int main()
{
while(cin>>N&&N!=0){
memset(Graph,125,sizeof(Graph));
for(int i = 1;i<N;i++){
char temp1;//表示每一行;
int totle;
cin>>temp1>>totle;
int x = temp1-'A'+1;
for(int i = 1;i<=totle;i++){
char temp2;
int value;
cin>>temp2>>value;
int y = temp2-'A'+1;
Graph[x][y]=value;
Graph[y][x] = value;
}
}//构造图成功;
// for(int i = 1;i<=N;i++){
// for(int j = 1;j<=N;j++)
// cout <<Graph[i][j]<<" ";
// cout <<endl;
// }
//
// 用克鲁斯卡尔算法
cout <<pu_G()<<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息