求最小生成树(Prim算法)
1000(ms)
10000(kb)
2256 / 4495
Tags: 生成树
求出给定无向带权图的最小生成树。图的定点为字符型,权值为不超过100的整形。在提示中已经给出了部分代码,你只需要完善Prim算法即可。
#include< iostream>
using namespace std;
typedef struct
{
int n;
int e;
char data[500];
int edge[500][500];
}Graph;
typedef struct
{
int index;
int cost;
}mincost;
typedef struct
{
int x;
int y;
int weight;
}EDGE;
typedef struct
{
int index;
int flag;
}F;
void create(Graph &G,int n ,int e)
{
int i,j,k,w;
char a,b;
for(i=0;i< n;i++)
cin>>G.data[i];
for(i=0;i< n;i++)
for(j=0;j< n;j++)
{
if(i==j)
G.edge[i][j]=0;
else
G.edge[i][j]=100;
}
for(k=0;k< e;k++)
{
cin>>a;
cin>>b;
cin>>w;
for(i=0;i< n;i++)
if(G.data[i]==a) break;
for(j=0;j< n;j++)
if(G.data[j]==b) break;
G.edge[i][j]=w;
G.edge[j][i]=w;
}
G.n=n;
G.e=e;
}
void Prim(Graph &G,int k)
{
//完成Prim算法
}
int main()
{
Graph my;
int n,e;
cin>>n>>e;
create(my,n,e);
Prim(my,0);
return 0;
}
输入
第一行为图的顶点个数n第二行为图的边的条数e接着e行为依附于一条边的两个顶点和边上的权值
输出
最小生成树中的边。
样例输入
6
10
ABCDEF
A B 6
A C 1
A D 5
B C 5
C D 5
B E 3
E C 6
C F 4
F D 2
E F 6
样例输出
(A,C)(C,F)(F,D)(C,B)(B,E)
#include<iostream>
#include<stdio.h>//新加的头文件
using namespace std;
typedef struct
{
int n;
int e;
char data[500];
int edge[500][500];
}Graph;
typedef struct
{
int index;
int cost;
}mincost;
typedef struct
{
int x;
int y;
int weight;
}EDGE;
typedef struct
{
int index;
int flag;
}F;
void create(Graph &G,int n ,int e)
{
int i,j,k,w;
char a,b;
for(i=0;i< n;i++)
cin>>G.data[i];
for(i=0;i< n;i++)
for(j=0;j< n;j++)
{
if(i==j)
G.edge[i][j]=0;
else
G.edge[i][j]=100;
}
for(k=0;k< e;k++)
{
cin>>a;
cin>>b;
cin>>w;
for(i=0;i< n;i++)
if(G.data[i]==a) break;
for(j=0;j< n;j++)
if(G.data[j]==b) break;
G.edge[i][j]=w;
G.edge[j][i]=w;
}
G.n=n;
G.e=e;
}
void Prim(Graph &G,int v) //将k改为v;
{
int lowcost[100];//用来储存相应序号的最短长度
int min;//用来标记长度
int closest[100],i,j,k;//closest作为标记,并且记录相应的点
for(i=0;i<G.n;i++)//将v=0,放入到树中,将到其他点到0点的长度依次储存在lowcost中
{
lowcost[i]=G.edge[v][i];
closest[i]=v;//将所有标记都赋值为0,并且将closest【0】赋值为相应的序号0!
}
for(i=1;i<G.n;i++)//已经将0点放入到树中,还有G.n-1个点需要放入,所以从 i=1开始
{
min=100;//初始化min
for(j=0;j<G.n;j++)//找出到放入树中的点的长度中最短的长度,并且用k记录该点
{
if(lowcost[j]!=0&&lowcost[j]<min)
{
min=lowcost[j];
k=j;
}
}
printf("(%c,%c)",closest[k]+'A',k+'A');//输出边,因为用相应的数字储存的,但是要输出字符,所以加上A的ascll码,即为相应的字母
lowcost[k]=0;//k点到树的长度标记为0,避免重复 ,并且k为刚放入树中的点
for(j=0;j<G.n;j++)
{
if(lowcost[j]!=0&&G.edge[k][j]<lowcost[j])//遍历刚放入树中的k那一行中是否有更短到树的长度
{
lowcost[j]=G.edge[k][j];//如果有,则将那个点到k点的长度储存在lowcost中对应位置
closest[j]=k;//将closest对应位置储存 相应序号。
}
}
}
}
int main()
{
Graph my;
int n,e;
cin>>n>>e;
create(my,n,e);
Prim(my,0);
return 0;
}
/*
#include<stdio.h>
int n;int map[100][100]={0};//初始化图
char str[100];int queue[100];
void Prim(int top)//top为队的长度
{
if(top<n)
{
int min=100,x,y;//初始化min的值,用来查找最小权重
for(int i=0;i<top;i++)
{
for(int j=0;j<n;j++)
{
if(map[queue[i]][j]<min&&map[queue[i]][j]!=0)//依次遍历队中的点对应的行 如果不为0,并且小于min,则改变min的值,并且记录行和列
{
min=map[queue[i]][j];
x=queue[i];
y=j;
}
}
}
for(int k=0;k<n;k++)//将能到达y点的图标记为0 ,避免重复
{
map[k][y]=0;
}
printf("(%c,%c)",str[x],str[y]);//输出边,即记录的行和列
queue[top++]=y;//并且将其入队
map[x][y]=0;//将该点的图标记为0,并且将其反向的点的图也标记为0
map[y][x]=0;
Prim(top);//继续递归直到所有的点都入队为止
}
}
int main()
{
int e;
scanf("%d",&n);
scanf("%d",&e);
scanf("%s",str);
for(int i=0;i<e;i++)
{
char a,b;int data;
getchar();//抵消回车字符
scanf("%c %c %d",&a,&b,&data);
map[a-'A'][b-'A']=data;//将字符结点变成相应的序号结点,并且创建无向图
map[b-'A'][a-'A']=data;
}
queue[0]=0;//将0点入队 ,从0行开始遍历
for(int k=0;k<n;k++)//将到达0点的图标记为0,避免重复
{
map[k][0]=0;
}
Prim(1);//1位当前队的长度
}
*/