PKU1679判断最小生成树是否唯一Prime算法

原题 http://poj.org/problem?id=1679
//本题是判断最小生成树是否唯一,可以根据先删除最小生成树里面的边然后新加入一条边,然后判断新生成的最小生成树的权值和原来是否相同
//这就要求要求原来最小生成树里任意两个点之间的最大值。

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <limits.h>
#include <ctype.h>
#include <string.h>
#include <string>
#include <algorithm>
#include <iostream>
//#include <stack>
#include <queue>
#include <deque>
#include <set>
#include <vector>
#include <math.h>
#include <set>
using namespace std;
#define INF 999999999
#define N 111
int n,m;
int pre[N],dis[N][N],max1[N][N],g[N];
int vis[N],stack[N];
int sum;

int max(int a,int b){
	if(a > b)
		return a;
	else
		return b;
}

int minn(int a,int b){
	if(a < b)
		return a;
	else
		return b;
}
void Prime(){
	int i,j,k;
	memset(vis,0,sizeof(vis));
	memset(g,0,sizeof(g));
	for(i=1;i<=n;i++){
		g[i] = dis[1][i];
		pre[i] = 1;
	}
	vis[1] = 0;
	int top=0;
	sum = 0;
	stack[top++] = 1;
	int tmp;
	for(i=1;i<=n;i++){
		tmp = INF;
		for(j=1;j<=n;j++){
			if(tmp>g[j] && vis[j]==0){
				tmp = g[j];
				k = j;
			}
		}
		vis[k] = 1;
		if(tmp == INF)
			break;
		sum+=tmp;
		for(j=0;j<top;j++){
			max1[stack[j]][k] = max(max1[stack[j]][pre[k]],tmp);//x新加入的点到最小生成树里面每个点的最大距离,前面的代表与这个点相连的那个,后面的代表选择出来的值
		}
			max1[k][stack[j]] = max1[stack[j]][k];
		}
		stack[top++] = k;
		for(j=1;j<=n;j++){
			if(vis[j]==0 && dis[k][j]<g[j]){
				g[j] = dis[k][j];
				pre[j] = k;
			}
		}
	}
}

int main(){
	int T;
	int i,j;
	int a,b,c;

	while(~scanf("%d",&T)){
		while(T--){
			scanf("%d%d",&n,&m);
			for(i=0;i<N;i++){
				for(j=0;j<N;j++){
					dis[i][j] = INF;
					max1[i][j] = 0;
				}
			}
			for(i=0;i<N;i++){
				dis[i][i] = 0;
			}
			for(i=1;i<=m;i++){
				scanf("%d%d%d",&a,&b,&c);
				dis[a][b] = c;
				dis[b][a] = c;
			}
			Prime();
			int min = INF;
			for(i=1;i<=n;i++){//遍历原最小生成树里面以外的任意边。
				for(j=1;j<=n;j++){
					if(i!=j && i!=pre[j] && j!=pre[i]){
						min = minn(min,dis[i][j]-max1[i][j]);
					}
				}
			}
			if(min != 0){
				printf("%d\n",sum);
			}
			else{
				printf("Not Unique!\n");
			}
		}
	}

	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值