UVA 10600 prim次小生成树

UVA 10600

  • 次小生成树prim板子
  • 代码第44行.发现更新最小生成树中的maxdist[][](2点之间的最大边),不能更新point,也就是刚加入生成树中的点,这样就会更新自环,变成了dist[point],而自环应该是0
#include <iostream>
#include <algorithm>
#include <string.h>

using namespace std;
const int maxn = 1e3 + 5;
const int INF = 0x3f3f3f3f;

bool vis[maxn];
int dist[maxn];
int e[maxn][maxn];
int n, m;
int sum;
bool use[maxn][maxn];
int maxdist[maxn][maxn];
int pre[maxn];

int prim() {
	sum = 0;
	memset(vis, 0, sizeof vis);
	memset(use, 0, sizeof use);
	memset(maxdist, 0, sizeof maxdist);
	vis[1] = 1; //点1加入到最小生成树中
	for (int i = 1; i <= n; i++) {
		dist[i] = e[1][i];
		pre[i] = 1;
	}
	dist[1] = 0;
	pre[1] = 0;

	for (int i = 1; i < n; i++) {
		int minn = INF;
		int point = INF;
		for (int j = 1; j <= n; j++) {
			if (!vis[j] && dist[j] < minn) {
				point = j;
				minn = dist[j];
			}
		}
		vis[point] = 1;
		sum += minn;
		use[point][pre[point]] = use[pre[point]][point] = 1; //标记在树的点
		for (int j = 1; j <= n; j++) { //更新每个点到树的距离
			if (vis[j] && j!=point) // j==point 更新的就是自环,自环应该为0,而这里会变成dist[point];  
				maxdist[j][point] = maxdist[point][j] = max(maxdist[j][pre[point]], dist[point]);
			if (!vis[j] && e[point][j] < dist[j]) {
				dist[j] = e[point][j];
				pre[j] = point; //既然更新了路径,也更新该点指向的上一个点
			}
		}
	}
	return sum;
}
int superprim() {
	int ans = INF;
	for (int i = 1; i <= n; i++) { //枚举所有的
		for (int j = 1; j <= n; j++) {
			if (!use[i][j] && e[i][j] != INF) {
				ans = min(sum + e[i][j] - maxdist[i][j], ans);
//				printf("ans=%d e[%d][%d]=%d maxdist[%d][%d]=%d\n",ans,i,j,e[i][j],i,j,maxdist[i][j]);
			}
		}
	}
	return ans;
}

int main() {
//	freopen("a.txt", "r", stdin);
	int times; cin >> times;
	while (times--) {
		scanf("%d%d",&n,&m);
		memset(e, 0x3f, sizeof e);
		for (int i = 1; i <= m; i++) {
			int u, v, w; scanf("%d%d%d",&u,&v,&w);
			e[u][v] = e[v][u] =  min(e[u][v],w);
		}
		prim(); int ans = superprim();
		printf("%d %d\n",sum, ans);
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值