【九度】题目1024:畅通工程

来源:互联网 发布:视觉训练软件banner 编辑:程序博客网 时间:2024/06/10 04:10

题目地址:http://ac.jobdu.com/problem.php?pid=1024
题目描述:

    省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可)。经过调查评估,得到的统计表中列出了有可能建设公路的若干条道路的成本。现请你编写程序,计算出全省畅通需要的最低成本。
输入:
    测试输入包含若干测试用例。每个测试用例的第1行给出评估的道路条数 N、村庄数目M (N, M < =100 );随后的 N 行对应村庄间道路的成本,每行给出一对正整数,分别是两个村庄的编号,以及此两村庄间道路的成本(也是正整数)。为简单起见,村庄从1到M编号。当N为0时,全部输入结束,相应的结果不要输出。
输出:
    对每个测试用例,在1行里输出全省畅通需要的最低成本。若统计数据不足以保证畅通,则输出“?”。
样例输入:
3 31 2 11 3 22 3 41 32 3 20 100
样例输出:
3?
来源:
2007年浙江大学计算机及软件工程研究生机试真题
解题思路:
       并查集的变形题。和题目1017:还是畅通工程其实完全一样,不同的就是一个是道路长度,一个代价大小。当然也可以使用prim来做。这在另外一道题目1417:变型金刚中有所体现。
      1、存储所有节点以及所花费用。
      2、排序。按照费用从小到大。
      3、根据value值从小到大做并查集操作,发现道路个数count == n-1的时候就退出。
      4、判断count是否小于n-1,如果成立的话,就说明所有道路并不能连通。否则输出道路长度。
 C++使用的是并查集,Java使用的算法是prim,都给出代码。
C++ AC
#include<stdio.h>#include<algorithm> const int maxn = 102;const int maxm = 102;int parent[maxn];using namespace std;struct Node{    int start;    int end;    int value;}nodes[maxm];    int compare(Node node1 ,Node node2){    if(node1.value < node2.value){        return 1;    }    return 0;}   int findParent(int f) {     while (parent[f] != f) {        f = parent[f];    }    return f;}  void unionTwo(int f, int t) {              int a = findParent(f);    int b = findParent(t);    if (a == b)        return;    if (a > b) {        parent[a] = b;    } else {        parent[b] = a;    }}    int main(){       int n;    int m;    while(scanf("%d%d",&m,&n)!=EOF){        if(m == 0){            break;        }        int i = 0;        for(i=0; i < m; i++){            scanf("%d%d%d" , &nodes[i].start, &nodes[i].end, &nodes[i].value);        }        sort(nodes,nodes+m,compare);        for(i = 1; i < n+1 ; i++){            parent[i] = i;        }        int minValue = 0;        int count = 0;        for (i = 0; i < m; i++) {            if (findParent(nodes[i].start) != findParent(nodes[i].end)) {                unionTwo(nodes[i].start,nodes[i].end);                minValue += nodes[i].value;                count++;                if(count == n-1){                    break;                }            }        }        if(count < n-1){            printf("?\n");        }else{            printf("%d\n", minValue);          }             }    return 0;}   /**************************************************************    Problem: 1024    User: wangzhenqing    Language: C++    Result: Accepted    Time:10 ms    Memory:1024 kb****************************************************************/

Java AC

import java.io.BufferedReader;import java.io.InputStreamReader;import java.io.StreamTokenizer;public class Main {    /*     * 1024     */    public static void main(String[] args) throws Exception {        StreamTokenizer st = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));        while (st.nextToken() != StreamTokenizer.TT_EOF) {            int n = (int) st.nval;            if (n == 0 ) {                break;            }            st.nextToken();             int m = (int) st.nval;              int cost[][] = new int[m+1][m+1];            for (int i = 1; i < m+1; i++) {                for (int j = 1; j < m+1; j++) {                    cost[i][j] = Integer.MAX_VALUE;                }            }            for (int i = 0; i < n; i++) {                st.nextToken();                 int a = (int) st.nval;                 st.nextToken();                 int b = (int) st.nval;                 st.nextToken();                 int d = (int) st.nval;                                  if (cost[a][b] > d ) {                    cost[a][b] = d;                    cost[b][a] = d;                }            }            int minCost[] = new int[m+1];            int visit[] = new int[m+1];            for (int i = 1; i < m+1; i++) {                minCost[i] = cost[1][i];            }            prime(cost , minCost , visit , m);        }    }    private static void prime(int[][] cost, int[] minCost, int[] visit, int m) {        minCost[1] = 0;        visit[1] = 1;        int minj = 1;        int resCost = 0;        for (int i = 1; i < m; i++) {            int min = Integer.MAX_VALUE;            for (int j = 1; j < m+1; j++) {                if (visit[j] == 0 && minCost[j] < min) {                    min = minCost[j];                    minj = j;                }            }            visit[minj] = 1;            resCost += min;            for (int j = 1; j < m+1; j++) {                if (visit[j] == 0 && minCost[j] > cost[minj][j]){                    minCost[j] = cost[minj][j];                }            }        }        int num = 0;        for (int i = 1; i < m + 1; i++) {            if (visit[i] == 1) {                num ++;            }        }        System.out.println(num == m ? resCost : "?");    }}     /**************************************************************    Problem: 1024    User: wzqwsrf    Language: Java    Result: Accepted    Time:160 ms    Memory:23512 kb****************************************************************/



原创粉丝点击