图的最小生成树

输入示例:

7 12
1 2 9
1 5 2
1 6 3
2 3 5
2 6 7
3 4 6
3 7 3
4 5 6
4 7 2
5 6 3
5 7 6
6 7 1
输出示例:

16

库鲁斯卡尔算法(用并查集)

#include<iostream>
#include<algorithm>
#include<sstream>
#include<math.h>
#include<vector>
#include<queue>
#include<list>
#include<map>
#include<set>
#include<string>
#include<stdio.h>
#include<ctype.h>
#include<cstring>
#include<cstdlib>
#include<iomanip>
using namespace std;
typedef long long ll;
int fa[2005];
struct line
{
	ll a, b, w;
	bool operator <(const line c)const
	{
		return w < c.w;
	}
}L[2005];
int find(int i)
{
	return i == fa[i] ? fa[i] : fa[i]=find(fa[i]);
}
int main()
{
	freopen("in.txt", "r", stdin);
	ios::sync_with_stdio(0);
	for (int i = 1; i <= 2004; i++)
	{
		fa[i] = i;
	}
	for (int i = 1; i <= 2004; i++)
	{
		L[i].w = 100000000000000005;
	}
	int n, m;
	cin >> n >> m;
	for (int i = 1; i <= m; i++)
	{
		ll w;
		cin >> L[i].a >> L[i].b >> w;
		L[i].w = min(L[i].w, w);
	}
	sort(L + 1, L + 1 + m);
	ll sum=0;
	for (int i = 1; i <= m; i++)
	{
		int a1 = find(L[i].a);
		int b1 = find(L[i].b);//并查集

		if (a1 != b1)
		{
			sum += L[i].w;
			fa[a1] = b1;//合并他们的父亲
		}
	}
	cout << sum;
}

普利姆算法:

#include<iostream>
#include<algorithm>
#include<sstream>
#include<math.h>
#include<vector>
#include<queue>
#include<list>
#include<map>
#include<set>
#include<string>
#include<stdio.h>
#include<ctype.h>
#include<cstring>
#include<cstdlib>
#include<iomanip>
using namespace std;
long long n, m, v[2005], d[2005], e[2005][2005];
int getMin()
{
    int i, mini = 0;/**< d[0]很大 */
    //这里利用d[0]在一开始不被储存数据
    for (i = 1; i <= n; i++)
        if (d[mini] > d[i] && v[i] == 0)
            mini = i;
    return mini;
}
long long prim()
{
    memset(d, 127 / 3, sizeof d);
    v[1] = 1;
    long long ans = 0;
    for (int i = 1; i <= n; i++)
        d[i] = e[1][i];
    for (int j = 1; j < n; j++)
    {
        int minnode = getMin();
        v[minnode] = 1;
        ans += d[minnode];//代表从刚刚选的那个节点开始找另外的点
        for (int i = 1; i <= n; i++)
            d[i] = min(d[i], e[minnode][i]);
    }
    return ans;
}
int main()
{
    long long i, j, x, y, z;
    memset(e, 127 / 3, sizeof e);
    cin >> n >> m;
    for (i = 1; i <= m; i++)
    {
        cin >> x >> y >> z;
        if (x == y)continue; //注意可能存在重边和自环。
        e[x][y] = e[y][x] = min(e[x][y], z);
    }
    cout << prim();
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值