[洛谷P3366] [模板] 最小生成树

存个模板,顺便复习一下kruskal和prim。

题目传送门

kruskal

稀疏图上表现更优。

设点数为n,边数为m。

复杂度:O(mlogm)。

先对所有边按照边权排序,初始化并查集的信息。

然后枚举每一条边,如果当前边的两个端点不在一个并查集里,就选上这条边。

如果图不连通会造成选的边数小于n-1。

如果成功生成了最小生成树,就会正好选n-1条边(树的性质)。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<queue>
 5 using namespace std;
 6 
 7 int n,m,cnt,ans;
 8 
 9 struct edge
10 {
11     int x,y,w;
12 }e[200005];
13 
14 int f[5005];
15 
16 int findfa(int p)
17 {
18     if(p==f[p])return p;
19     f[p]=findfa(f[p]);
20     return f[p];
21 }
22 
23 int cmp(edge q,edge r)
24 {
25     return q.w<r.w;
26 }
27 
28 void kruskal()
29 {
30     sort(e+1,e+m+1,cmp);
31     for(int i=1;i<=m;i++)
32     {
33         int fx=findfa(e[i].x);
34         int fy=findfa(e[i].y);
35         if(fx==fy)continue;
36         ans+=e[i].w;
37         cnt++;
38         f[fx]=fy;
39     }
40 }
41 
42 int main()
43 {
44     scanf("%d%d",&n,&m);
45     for(int i=1;i<=n;i++)f[i]=i;
46     for(int i=1;i<=m;i++)
47         scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].w);
48     kruskal();
49     if(cnt<n-1)printf("orz");
50     else printf("%d",ans);
51     return 0;
52 }

prim

稠密图上表现更优。

时间复杂度:O(nlogn+m)。

算法很像dijkstra求最短路。

只不过这个是维护某个点到已选的点组成的点集的距离,而不是到源点的距离。

初始先随便选一个点,把这个点的距离设为0,剩下的点的距离设为0x3f3f3f3f。

然后就很像dijkstra......

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<queue>
 5 using namespace std;
 6 
 7 int n,m,cnt,ans;
 8 int hd[5005],nx[400005],to[400005],len[400005],ec;
 9 int dis[5005],v[5005];
10 
11 void edge(int af,int at,int ev)
12 {
13     to[++ec]=at;
14     nx[ec]=hd[af];
15     len[ec]=ev;
16     hd[af]=ec;
17 }
18 
19 struct data
20 {
21     int ps,ds;
22     friend bool operator<(data q,data w)
23     {
24         return q.ds>w.ds;
25     }
26 };
27 
28 priority_queue<data>qq;
29 
30 void prim()
31 {
32     memset(dis,0x3f,sizeof(dis));
33     dis[1]=0,cnt++;
34     qq.push((data){1,0});
35     while(!qq.empty()&&cnt<=n)
36     {
37         data p=qq.top();
38         qq.pop();
39         if(v[p.ps])continue;
40         v[p.ps]=1;
41         cnt++;
42         ans+=p.ds;
43         for(int i=hd[p.ps];i;i=nx[i])
44         {
45             if((dis[to[i]]>len[i])&&(!v[to[i]]))
46             {
47                 dis[to[i]]=len[i];
48                 qq.push((data){to[i],dis[to[i]]});
49             }
50         }
51     }
52 }
53 
54 int main()
55 {
56     scanf("%d%d",&n,&m);
57     for(int i=1;i<=m;i++)
58     {
59         int x,y,z;
60         scanf("%d%d%d",&x,&y,&z);
61         edge(x,y,z);
62         edge(y,x,z);
63     }
64     prim();
65     if(cnt<n)printf("orz");
66     else printf("%d",ans);
67     return 0;
68 }

猜你喜欢

转载自www.cnblogs.com/eternhope/p/9756262.html