做题时发现自己只会打(Kruskal) kk/,所以来补课来了
概念
(v) 个点的无向图中,取 (|v| - 1)条边,组成的权值最小的树
prim
mind:
将顶点分为两类,一类是在查找的过程中已经包含在树中的(假设为 A 类),剩下的是另一类(假设为 B 类),起始状态全部顶点都归为 B 类。在找最小生成树时,选定任意一个顶点作为起始点,并将之从 B 类移至 A 类;然后找出 B 类中到 A 类中的顶点之间权值最小的顶点,将之从 B 类移至 A 类,如此重复,直到 B 类中没有顶点为止。所走过的顶点和边就是该连通图的最小生成树
#include<bits/stdc++.h>
using namespace std;
#define re register
#define il inline
il int read()
{
re int x=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
return x*f;
}
#define inf 123456789
#define A 5005
#define B 200005
struct edge{
int v,w,next;
}e[B<<1];
int head[A],dis[A],cnt,n,m,tot,now=1,ans;
bool vis[B];
il void add(int u,int v,int w)
{
e[++cnt].v = v;e[cnt].w = w;e[cnt].next = head[u];head[u] = cnt;
}
il void init()
{
n = read(),m = read();
for(re int i = 1,u,v,w;i <= m;++i){
u = read(),v = read(),w = read();
add(u,v,w),add(v,u,w);
}
}
il int prim()
{
for(re int i = 2;i <= n; ++i) dis[i] = inf;
for(re int i = head[1];i;i = e[i].next){
dis[e[i].v] = min(dis[e[i].v],e[i].w);
}
while(++tot<n){
re int minn = inf;
vis[now] = 1;
for(re int i = 1;i <= n;++i){
if(!vis[i]&&minn > dis[i]){
minn = dis[i];
now = i;
}
}
ans += minn;
for(re int i = head[now];i;i = e[i].next){
re int v = e[i].v;
if(dis[v] > e[i].w&&!vis[v]){
dis[v] = e[i].w;
}
}
}
return ans;
}
int main(){
init();
printf("%d",prim());
return 0;
}
Kruskal
选取权值较小的边,并依次连接,若出现环则跳过此边(用并查集来判断是否存在环)继续搜,直到已经使用的边的数量比总点数少一即可
/*
work by:Ariel
*/
#include<iostream>
#include<cstdio>
#include<queue>
#include <algorithm>
using namespace std;
const int M = 500010;
int read(){
int f = 1,x = 0;char c = getchar();
while(c < '0'||c > '9'){if(c == '-')f = -1,c = getchar();}
while(c <= '9'&&c >= '0'){x = x*10 + c - '0',c = getchar();}
return f*x;
}
struct edge{
int u,v,w;
}e[M];
int n,m,fa[M];
int find(int x){
if(fa[x] == x) return x;
return fa[x] = find(fa[x]);
}
int cmp(edge x,edge y){
return x.w < y.w;
}
int pd(int x,int y){//判断x,y是否在图上
int a = find(x);
int b = find(y);
if(a != b){
fa[b] = a;
return 1;
}
return 0;
}
int main()
{
n = read(),m = read();
for (int i = 1;i <= m; i++){
scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
}
int cnt = 0,ans = 0;
sort(e + 1,e + m + 1,cmp);
for (int i =1 ;i <= n; i++)
fa[i] = i;
for (int i = 1;i <= m; i++){
if (pd(e[i].u,e[i].v) == 1){
cnt ++;
ans += e[i].w;
}
if(cnt == n-1) break;
}
if(cnt == n-1) printf("%d",ans);
else printf("orz");
return 0;
}