题目描述
根据输入创建无向网。分别用Prim算法和Kruskal算法构建最小生成树。(假设:输入数据的最小生成树唯一。)
输入
顶点数n
n个顶点
边数m
m条边信息,格式为:顶点1 顶点2 权值
Prim算法的起点v
输出
输出最小生成树的权值之和
对两种算法,按树的生长顺序,输出边信息(Kruskal中边顶点按数组序号升序输出)
样例输入
6 v1 v2 v3 v4 v5 v6 10 v1 v2 6 v1 v3 1 v1 v4 5 v2 v3 5 v2 v5 3 v3 v4 5 v3 v5 6 v3 v6 4 v4 v6 2 v5 v6 6 v1样例输出
15 prim: v1 v3 1 v3 v6 4 v6 v4 2 v3 v2 5 v2 v5 3 kruskal: v1 v3 1 v4 v6 2 v2 v5 3 v3 v6 4 v2 v3 5提示
#include<iostream> #include<queue> #include<cstring> using namespace std; #define INF 0x3f #define maxx 0x3f3f3f3f #define in e #define bef x1 #define aft x2 int array[INF][INF]; int visit[INF]; int n; int e; class edge { public: int x1; int x2; int data; int flag; edge() { x1=x2=-1; data=0; flag=0; } edge(int n1,int n2,int weight) { x1=n1; x2=n2; data=weight; flag=0; } friend bool operator>(const edge &a,const edge &b) { if(a.data>b.data) return true; else return false; } }; int find(string str[],string st) { for(int i=0;i<n;i++) { if(str[i]==st) return i; } return -1; } int check() { for(int i=0;i<n;i++) { if(visit[i]==0) return 1; } return 0; } void prim(string str[],int start) { memset(visit,0,sizeof(visit)); int index=start; int sum=0; priority_queue< edge,vector<edge>,greater<edge> >T; string savex1[INF]; string savex2[INF]; int savew[INF]; int count=0; while(check()) { for(int i=0;i<n;i++) { if(array[index][i]!=maxx) { edge temp(index,i,array[index][i]); T.push(temp); } } while(visit[T.top().x2]==1) { T.pop(); } savex1[count]=str[T.top().x1]; savex2[count]=str[T.top().x2]; savew[count]=T.top().data; sum+=T.top().data; visit[T.top().x1]=1; visit[T.top().x2]=1; count++; index=T.top().x2; T.pop(); } cout<<sum<<endl; cout<<"prim:"<<endl; for(int i=0;i<count;i++) { cout<<savex1[i]<<" "<<savex2[i]<<" "<<savew[i]<<endl; } } int findmin(edge kr[]) { int minn=0x3f3f3f3f; int index=0; for(int i=0;i<in;i++) { if(!kr[i].flag&&kr[i].data<minn) { minn=kr[i].data; index=i; } } return index; } void change(int tag[],int a,int b) { for(int i=0;i<n;i++) if(tag[i]==a) tag[i]=b; } void kruskal(string str[],edge kr[]) { int visit[n]; for(int i=0;i<n;i++) visit[i]=i; cout<<"kruskal:"<<endl; int k=0; while(true) { int minn=findmin(kr);///找出权重最小的边 kr[minn].flag=1; int t1=kr[minn].bef; int t2=kr[minn].aft; if(visit[t1]!=visit[t2]) { if(t1>t2) swap(t1,t2); cout<<str[t1]<<" "<<str[t2]<<" "<<kr[minn].data<<endl; change(visit,visit[t1],visit[t2]);///将两个顶点连通 } k++; if(k>=in) break; } } int main() { cin>>n; string str[n]; for(int i=0;i<n;i++) cin>>str[i]; for(int i=0;i<n;i++) for(int j=0;j<n;j++) array[i][j]=maxx; cin>>e; edge kr[e]; for(int j=0;j<e;j++) { string s1; string s2; int weight; cin>>s1>>s2>>weight; int t1=find(str,s1); int t2=find(str,s2); array[t1][t2]=weight; array[t2][t1]=weight; //krushal kr[j].bef=t1; kr[j].aft=t2; kr[j].data=weight; kr[j].flag=0; } string s; cin>>s; int d=find(str,s); prim(str,d); kruskal(str,kr); return 0; }