最小生成樹

作題時發現本身只會打\(Kruskal\) kk/,因此來補課來了ios

概念

\(v\) 個點的無向圖中,取 \(|v| - 1\)條邊,組成的權值最小的樹c++

prim

mind:spa

將頂點分爲兩類,一類是在查找的過程當中已經包含在樹中的(假設爲 A 類),剩下的是另外一類(假設爲 B 類),起始狀態所有頂點都歸爲 B 類。在找最小生成樹時,選定任意一個頂點做爲起始點,並將之從 B 類移至 A 類;而後找出 B 類中到 A 類中的頂點之間權值最小的頂點,將之從 B 類移至 A 類,如此重複,直到 B 類中沒有頂點爲止。所走過的頂點和邊就是該連通圖的最小生成樹code

#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

選取權值較小的邊,並依次鏈接,若出現環則跳過此邊(用並查集來判斷是否存在環)繼續搜,直到已經使用的邊的數量比總點數少一便可get

/*
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;
}
相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息