第一行國際慣例——咕咕咕。
本代碼以sdnu1218爲例
1.類似貪心的策略,先對邊按權值進行排序,不停的選擇最優邊進行構建樹
2.在構建過程中需要判斷是否有環(並查集判斷(如果不會並查集(我改天再補一下並查集博客
3.忽略我特別醜的代碼風格
4.可以增加優化(在kruskal函數的循環里加一個提前跳出的操作,當邊的個數>n-1時跳出即可(n爲點的個數(最小生成樹最多n-1條邊(此處略過
5.時間複雜度與邊的個數有關(適合稀疏圖
6.先寫kruskal是因爲我prim不會寫(這個晚上看了2/3時間的prim都不會寫(我果然菜的很
#include <iostream>
#include <cstdio>
#include <algorithm>
#define inf 999999999999
#define maxn 200005
using namespace std;
int fa[maxn];
int n,m;
struct tree
{
int u;
int v;
int cost;
} t[maxn];//用於存每條邊
void init()
{
for(int i=0; i<maxn; ++i)
{
t[i].cost=inf;
fa[i]=i;
}
}//初始化所有的權值爲max,所有的父節點爲其本身
bool com(tree x,tree y)
{
if(x.cost<y.cost)
return true;
else
return false;
}//按權值從小到大排序
int tofind(int x)
{
while(fa[x]!=x)
{
x=fa[x];
}
return x;
}//找到每個點的父節點
void tojoin(int x,int y)
{
x=tofind(x);
y=tofind(y);
if(x!=y)
fa[x]=y;
}//合併兩棵樹
int kruskal()
{
int ans=0;
for(int i=0; i<m; ++i)
{
int u=t[i].u;
int v=t[i].v;
if(tofind(u)==tofind(v))
continue;//當兩個點的父節點爲同一節點(即早已聯通,下一個循環
ans+=t[i].cost;
tojoin(u,v);//合併兩個爲同一個棵樹
}
return ans;
}
int main()
{
init();
scanf("%d%d",&n,&m);
for(int i=0; i<m; ++i)
{
int u,v,cost;
scanf("%d%d%d",&t[i].u,&t[i].v,&t[i].cost);
}//將每個邊儲存
sort(t,t+m,com);//排序
printf("%d\n",kruskal());
return 0;
}
//後期應該會更新幾個練習題