在数据结构中我们知道最小生成树有两种实现方法,这两种方法一定要熟练,其中prim方法开了两个辅助数组vis[]和dis[];kruskal方法采用了并查集并可以和优先队列(也可以直接用sort排序)结合起来,下面是个人两种方法在邻接表中的实现代码:
#include<iostream> #include<vector> #include<queue> using namespace std; const int maxv=1000; const int maxe=1000; const int inf=100000000; int n,e;// 结点数,边数 struct node{ int vex,weight; }; vector<node>Adj[maxv];//定义邻接表 //prim算法部分 bool vis[maxv];//区别访问和未访问的集合 int dis[maxv];//更新各结点到集合最短距离 int prim() {//返回最小生成树之和 for(int i=0;i<n;i++){ //初始化 vis[i]=false; dis[i]=inf; } vis[0]=true; //v0点入集合 int k=0,min;//标记当前入集合结点 int sum=0;//记录最小路径和 for(int j=1;j<n;j++) { //剩余n-1个结点 min=inf; for(int i=0;i<Adj[k].size();i++){ //更新dis int v=Adj[k][i].vex; if(Adj[k][i].weight<dis[v]) dis[v]=Adj[k][i].weight; } for(int i=0;i<n;i++) { if(!vis[i]&&dis[i]<min) { k=i; min=dis[i]; } } if(min==inf)return -1;//图不连通 sum+=min; vis[k]=true; } return sum; } //kruskal算法部分 int father[maxe];//并查集 struct edge{ int x,y;//边两顶点 int weight;//边权 edge(int a,int b,int c){ x=a; y=b; weight=c; } edge(){ } }Edge[maxe]; struct cmp{ bool operator ()( int a,int b){ return Edge[a].weight>Edge[b].weight; } }; priority_queue<int,vector<int>,cmp>q;//优先队列存放最小边权下标 int kruskal() { int sum=0;//记录最小路径和 for(int i=0;i<e;i++) {father[i]=i;//并查集初始化 q.push(i) ;//优先队列存放边 } int temp=q.top();q.pop(); //先选出第一条边 sum+=Edge[temp].weight; int k=Edge[temp].x; //标记该集合 father[Edge[temp].y] =k; for(int i=2;i<n;i++) {//选剩下n-2条边 while(father[Edge[temp].x]==father[Edge[temp].y]&&!q.empty()) { temp=q.top();q.pop(); //选出非闭环的边 } if(father[Edge[temp].x]==father[Edge[temp].y])//先不出边 return -1; sum+=Edge[temp].weight; //标记该集合 father[Edge[temp].y] =father[Edge[temp].x]=k; //并入集合 ,路径压缩 } return sum; } int main(){ scanf("%d%d",&n,&e); int x,y,w; node temp; for(int i=0;i<e;i++) //初始化邻接表和边表 { scanf("%d%d%d",&x,&y,&w); temp.vex=y;temp.weight=w; Adj[x].push_back(temp); edge k(x,y,w); Edge[i]=k; } printf("%d\n",prim()) ; printf("%d\n",kruskal()) ; return 0; }
这个部分应该多刷题以熟练应用,算是一个重点。