还是畅通工程

题目

题目描述:
    某省调查乡村交通状况,得到的统计表中列出了任意两村庄间的距离。省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可),并要求铺设的公路总长度为最小。请计算最小的公路总长度。
输入:
    测试输入包含若干测试用例。每个测试用例的第1行给出村庄数目N ( < 100 );随后的N(N-1)/2行对应村庄间的距离,每行给出一对正整数,分别是两个村庄的编号,以及此两村庄间的距离。为简单起见,村庄从1到N编号。
    当N为0时,输入结束,该用例不被处理。
输出:
    对每个测试用例,在1行里输出最小的公路总长度。
样例输入:
3
1 2 1
1 3 2
2 3 4
4
1 2 1
1 3 4
1 4 1
2 3 3
2 4 2
3 4 5
0
样例输出:
3
5

思路

这道题目是典型的求最小生成树的题目,因此有两种思路:
  • kurskal算法
  • prim算法

AC代码

分别show出两种算法的ac代码

prim算法

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define INF 10000000
 
int map[101][101];
 
void init_map(int n)
{
    int i, j;
 
    for (i = 1; i <= n; i ++) {
        for (j = 1; j <= n; j ++) {
            map[i][j] = INF;
        }
    }
}
 
int prim(int n)
{
    int lowcost[101], visited[101];
    int minc, i, j;
    int res = 0, mnt;
 
    memset(visited, 0, sizeof(visited));
 
    for (i = 1; i <= n; i ++) {
        lowcost[i] = map[1][i];
    }
    visited[1] = 1;
 
    for (i = 1; i < n; i ++) {
        minc = INF;
        mnt = -1;
     
        for (j = 1; j <= n; j ++) {
            if (visited[j] == 0 && minc > lowcost[j]) {
                minc = lowcost[j];
                mnt = j;
            }
        }
 
        if (mnt == -1) 
            return -1;
 
        res += minc;
 
        visited[mnt] = 1;
 
        for (j = 1; j <= n; j ++) {
            if (visited[j] == 0 && lowcost[j] > map[mnt][j]) {
                lowcost[j] = map[mnt][j];
            }
        }
    }
    return res;
}
 
 
int main()
{
    int i, n, en, u, v, len, res;
 
    while (scanf("%d", &n) != EOF && n) {
        init_map(n);
         
        en = n * (n - 1) / 2;
         
        for (i = 0; i < en; i ++) {
            scanf("%d %d %d", &u, &v, &len);
            map[u][v] = map[v][u] = len;
        }
     
        // prime求最小生成树
        res = prim(n);
 
        printf("%d\n", res);
    }
 
    return 0;
}
/**************************************************************
    Problem: 1017
    User: wangzhengyi
    Language: C
    Result: Accepted
    Time:20 ms
    Memory:948 kb
****************************************************************/


kruskal算法

#include <stdio.h>
#include <stdlib.h>

int father[101];

struct road
{
	int u, v, len;
};

int compare(const void *p, const void *q);
int find_set(int x);
void union_set(int x, int y);

int main()
{
	int n, m, i, pu, pv, mst;
	struct road path[5100];

	while (scanf("%d", &n) != EOF && n != 0) {
		for (i = 1; i <= n; i ++) {
			father[i] = i;
		}
		m = n * (n - 1) / 2;

		for (i = 0; i < m; i ++) {
			scanf("%d %d %d", &path[i].u, &path[i].v, &path[i].len);
		}

		qsort(path, m, sizeof(path[0]), compare);

		for (i = mst = 0; i < m; i ++) {
			pu = find_set(path[i].u);
			pv = find_set(path[i].v);
			if (pu != pv) {
				mst += path[i].len;
				union_set(pu, pv);
			}
		}

		printf("%d\n", mst);
	}
		
	return 0;
}

int compare(const void *p, const void *q)
{
	const struct road *a = p;
	const struct road *b = q;

	return a->len - b->len;
}

int find_set(int x)
{
	while (father[x] != x) {
		x = father[x];
	}

	return x;
}

void union_set(int x, int y)
{
	int px, py;
	px = find_set(x);
	py = find_set(y);

	if (px != py) {
		father[px] = py;
	}
}


posted @ 2013-04-15 17:54  java程序员填空  阅读(128)  评论(0编辑  收藏  举报