HDU 1879 继续畅通工程

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wlh1998/article/details/76026515
#include<stdio.h>
#include<string.h>

const int INF = 0x3f3f3f3f;
const int maxn = 1e3;

int fa[maxn];
int mp[maxn][maxn];  // 存图; 
int vis[maxn];  //是否在新图内; 
int dis[maxn];  //第i个顶点到新图最短距离; 
int prim(int n);

int find(int x){
	return fa[x] == x ? x : fa[x] = find(fa[x]);
}

int main (){
	
	int m;
	int cun1,cun2,cost,ans = 0,flag;
	while (scanf("%d", & m) != EOF && m != 0){
		memset(mp,0x3f,sizeof(mp));
		memset(vis,0,sizeof(vis));
		for (int i = 0; i < maxn; i++){
			fa[i] = i;
		}
		for (int i = 0; i < m * (m-1) / 2; i++){
			scanf("%d%d%d%d", &cun1,&cun2,&cost, &flag);
			cun1--;
			cun2--;
			mp[cun1][cun2] = cost;
			mp[cun2][cun1] = cost;
			if (flag == 1){
				fa[find(cun2)] = find(cun1);
				mp[cun1][cun2] = 0;
				mp[cun2][cun1] = 0;
			}
		}
		ans = prim(m);
		printf("%d\n",ans);
	}
}

int prim(int n){
	int ans = 0;
	int m = 0;
	
	for (int i = 0; i < n; i++){
		if(find(i) == i) {
			m++;
		}
	}

	for (int i = 0; i < n; i++)	dis[i] = mp[0][i]; 
	for (int i = 0; i < n; i++){
		if (find(i) == find(0)){
			vis[i] = 1;
			dis[i] = 0;
		}
	}
	for (int i = 1; i < n; i++){
		if (vis[i]){
			for (int j = 0; j < n; j++) {
				if (!vis[j] && mp[i][j] < dis[j]){
					dis[j] = mp[i][j];
				}
			}			
		}
	}
	for (int i = 1; i < n; i++){  
		int minn = INF;  // 旧图到新图最短距离 
		int pos = -1;    // 旧图最近点标号; 
		for (int j = 0; j < n; j++){
			if(!vis[j] && minn > dis[j]) {
				minn = dis[j];
				pos = j;
			}
		}
		if (minn == INF) return ans;
		ans += minn;     //更新答案; 
		vis[pos] = 1;
		for (int j = 0; j < n; j++){
			if (find(j) == find(pos)){
				vis[j] = 1;
				dis[j] = 0;
			}
		}
			for (int i = 1; i < n; i++){
				if (vis[i]){
					for (int j = 0; j < n; j++) {
						if (!vis[j] && mp[i][j] < dis[j]){
							dis[j] = mp[i][j];
						}
					}			
				}
			}
	}
	return ans;
}
前一个写的很复杂,各种合并出错,每次更新需遍历整个图,最初这wa了几发
//畅通工程修过直接cost为零过
//并不知道之前哪错了。。。。。。 
#include<stdio.h>
#include<string.h>

const int INF = 0x3f3f3f3f;
const int maxn = 1e3;

int fa[maxn];
int mp[maxn][maxn];  // 存图; 
int vis[maxn];  //是否在新图内; 
int dis[maxn];  //第i个顶点到新图最短距离; 
int prim(int n);

int find(int x){
	return fa[x] == x ? x : fa[x] = find(fa[x]);
}

int main (){
	
	int m;
	int cun1,cun2,cost,ans = 0,flag;
	while (scanf("%d", & m) != EOF && m != 0){
		memset(mp,0x3f,sizeof(mp));
		memset(vis,0,sizeof(vis));
		for (int i = 0; i < maxn; i++){
			fa[i] = i;
		}
		for (int i = 0; i < m * (m-1) / 2; i++){
			scanf("%d%d%d%d", &cun1,&cun2,&cost, &flag);
			cun1--;
			cun2--;
			mp[cun1][cun2] = cost;
			mp[cun2][cun1] = cost;
			if (flag == 1){
				mp[cun1][cun2] = 0;
				mp[cun2][cun1] = 0;
			}
		}
		ans = prim(m);
		printf("%d\n",ans);
	}
}

int prim(int n){
	int ans = 0;
	memset(vis,0,sizeof(vis));
	vis[0] = 1;   //注意第一个点的初始化; 
	for (int i = 0; i < n; i++)	dis[i] = mp[0][i]; // 新图第一个点为0,初始化dis; 
	for (int i = 1; i < n; i++){  // 加入第i+1个点 
		int minn = INF;  // 旧图到新图最短距离 
		int pos = -1;    // 旧图最近点标号; 
		for (int j = 0; j < n; j++){
			if(!vis[j] && minn > dis[j]) {
				minn = dis[j];
				pos = j;
			}
		}
		if (minn == INF) return -1;
		ans += minn;     //更新答案; 
		vis[pos] = 1;
		
		for (int j = 0; j < n; j++) {
			if (!vis[j] && mp[pos][j] < dis[j]){
				dis[j] = mp[pos][j];
			}
		}
	}
	return ans;
}

猜你喜欢

转载自blog.csdn.net/wlh1998/article/details/76026515