求最小生成樹(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位當前隊的長度
}
*/