SWUST OJ 1075 求最小生成树(Prim算法)

求最小生成树(Prim算法)

我对提示代码做了简要分析,提示代码大致写了以下几个内容

  1. 给了几个基础的工具,邻接表记录图的一个的结构体,记录Prim算法中最近的边的结构体,记录目标边的结构体(始末点,值)。
  2. 初始化记录了图,规定了从0号节点开始构建。
    给了这么多东西,不能不用,对吧,下面就是题目以及算法

1000(ms) 10000(kb) 2490 / 4945
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; //没懂拿来干嘛

//一个形成图的函数。对角存为0(无边连接自己),其他存为100
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)

ok,先说我的思路:

  • 大致描述为,循环n-1次(n-1个边),每次找一个边
  • 遍历所有遍历过的节点,找与所有节点连接的节点,(未被遍历过,这样符合逻辑,同时避免回路)两节点形成的边中值最小的边(从已知节点中找与已经构成的连接最近的节点)
  • 输出这个边,并重置记录最小值的变量,记录新节点已遍历

其中,用visited[]数组来标识节点是否已经遍历,

#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) 
{ 
	Mincost mincost;
	EDGE edge;
	int visited[G.n];
	for(int i=0;i<G.n;i++)
	{
		visited[i]=0;
	}
	mincost.cost=99999;
	mincost.index=0;
	visited[k]=1;
	//G.n-1个边,找G.n-1次
	for(int i=k;i<G.n-1;i++)
	{
		//从第一个节点连接的节点开始找目标节点
		for(int j=0;j<G.n;j++)
		{
			if(visited[j]==1)//已经构造的图中有此节点
			{
			for(int l=0;l<G.n;l++)
			{
				if(G.edge[j][l]!=0)//有该边
				{
					if(visited[l]==0)//该节点未被遍历过
					{
						if(G.edge[j][l]<mincost.cost)//是更小的边,更小哦
						{
							mincost.index=l;
							mincost.cost=G.edge[j][l];
							edge.weight=G.edge[j][l];
							edge.x=j;
							edge.y=l;
						}
					}
				}
			}
		}
		}
		//输出,保存,重置
		visited[mincost.index]=1;
		cout<<'('<<G.data[edge.x]<<','<<G.data[edge.y]<<')';
		mincost.cost=99999;
		mincost.index=0;
	}
} 

int main() 
{ 
Graph my; 
int n,e; 
cin>>n>>e; 
create(my,n,e); 
Prim(my,0);    
return 0; 
} 
posted @ 2019-05-15 21:31  jirath  阅读(361)  评论(0编辑  收藏  举报