实验1-1Prime

问题:

Prim算法构造最小生成树的过程。

解析:

Prim算法的基本思路:    

从一个点出发,找到该点相连的边的最短边,把这条边的另一个端点加入点集。不断找点集中点相连的最短边,若该边的另一个端点也在点集中,则找次短边;若该边的另一个端点不在点集中,则将该点加入点集,直到所有的点都在点集中。

解析图:

 设计(核心代码):

 1 int prime()
 2 {
 3     //在优先队列中放入第一个点所连的边
 4     vis[1]=1,cnt++;
 5     for(int i=head[1];i!=-1;i=p[i].next)    q.push(p[i]);
 6     //还有点没在点集中
 7     while(cnt!=n)
 8     {
 9         edge e=q.top();q.pop();
10         //如果相连的点已经在点集中了
11         while(vis[e.v]==1)    e=q.top(),q.pop();
12         vis[e.v]=1,cnt++,ans+=e.w;//把该点放入点集,更新答案
13         for(int i=head[e.v];i!=-1;i=p[i].next)
14             if(!vis[p[i].v])    q.push(p[i]);//把该点所连的边放入优先队列
15     }
16     return ans;
17 }

源码:

https://github.com/Big-Kelly/Algorithm

  1 #include<bits/stdc++.h>
  2 #include <set>
  3 #include <map>
  4 #include <stack>
  5 #include <cmath>
  6 #include <queue>
  7 #include <cstdio>
  8 #include <string>
  9 #include <vector>
 10 #include <cstring>
 11 #include <iostream>
 12 #include <algorithm>
 13 
 14 #define ll long long
 15 #define PLL pair<ll,ll>
 16 #define PII pair<int,int>
 17 #define bug printf("*********\n")
 18 #define FIN freopen("input.txt","r",stdin);
 19 #define FON freopen("output.txt","w+",stdout);
 20 #define IO ios::sync_with_stdio(false),cin.tie(0)
 21 #define ls root<<1
 22 #define rs root<<1|1
 23 
 24 using namespace std;
 25 const int inf=0x3f3f3f3f;
 26 const ll Inf=1e18+7;
 27 const int maxn=1e4+5;
 28 const int mod=1e9+7;
 29 
 30 struct Prime
 31 {
 32     //链式前向星存边
 33     struct edge
 34     {
 35         int v,w,next;
 36     }p[maxn];
 37 
 38     int tot,head[maxn];
 39 
 40     void add(int u,int v,int w)
 41     {
 42         p[tot].v=v,p[tot].w=w,p[tot].next=head[u];
 43         head[u]=tot++;
 44     }
 45 
 46     int vis[maxn],n;//标记点是否在点集中。
 47 
 48     void init()//初始化
 49     {
 50         tot=0;
 51         memset(head,-1,sizeof head);
 52         memset(vis,0,sizeof vis);
 53     }
 54 
 55     //优先队列处理最短边
 56     struct cmp
 57     {
 58         bool operator()(const edge &a,const edge &b)
 59         {
 60             return a.w>b.w;
 61         }
 62     };
 63     priority_queue<edge,vector<edge>,cmp > q;
 64 
 65     int ans=0;//最小生成树的权值和
 66     int cnt=0;//点集中点的个数
 67 
 68     int prime()
 69     {
 70         //在优先队列中放入第一个点所连的边
 71         vis[1]=1,cnt++;
 72         for(int i=head[1];i!=-1;i=p[i].next)    q.push(p[i]);
 73         //还有点没在点集中
 74         while(cnt!=n)
 75         {
 76             edge e=q.top();q.pop();
 77             //如果相连的点已经在点集中了
 78             while(vis[e.v]==1)    e=q.top(),q.pop();
 79             vis[e.v]=1,cnt++,ans+=e.w;//把该点放入点集,更新答案
 80             for(int i=head[e.v];i!=-1;i=p[i].next)
 81                 if(!vis[p[i].v])    q.push(p[i]);//把该点所连的边放入优先队列
 82         }
 83         return ans;
 84     }
 85 };
 86 
 87 int n,m;
 88 
 89 int main()
 90 {
 91     freopen("in.txt","r",stdin);
 92     freopen("out.txt","w",stdout);
 93     Prime p;
 94     scanf("%d %d",&n,&m);
 95     p.n=n;
 96     p.init();
 97     while(m--)
 98     {
 99         int u,v,w;
100         scanf("%d %d %d",&u,&v,&w);
101         p.add(u,v,w);
102         p.add(v,u,w);
103     }
104     printf("%d\n",p.prime());
105 }
View Code

 

猜你喜欢

转载自www.cnblogs.com/zhang-Kelly/p/12382846.html
今日推荐