MOOC浙大数据结构 — 08-图7 公路村村通 (30分)


现有村落间道路的统计数据表中,列出了有可能建设成标准公路的若干条道路的成本,求使每个村落都有公路连通所需要的最低成本。

输入格式:

输入数据包括城镇数目正整数NN\le 10001000)和候选道路数目MM\le 3N3N);随后的MM行对应MM条道路,每行给出3个正整数,分别是该条道路直接连通的两个城镇的编号以及该道路改建的预算成本。为简单起见,城镇从1到NN编号。

输出格式:

输出村村通需要的最低成本。如果输入数据不足以保证畅通,则输出-11,表示需要建设更多公路。

输入样例:

6 15
1 2 5
1 3 3
1 4 7
1 5 4
1 6 2
2 3 4
2 4 6
2 5 2
2 6 6
3 4 6
3 5 1
3 6 1
4 5 10
4 6 8
5 6 3

输出样例:

12

#include <cstdio>
#include <algorithm>

#define MAX 1000
#define INF 0x3fffffff

using namespace std;

int N, M;

int MGraph[MAX][MAX];
int dist[MAX] = { 0 };
int parent[MAX] = { 0 };
int father[MAX] = { 0 };

typedef struct {
    int start;
    int end;
    int weight;
} Edge;
Edge edge[MAX * 3] = { 0 };

void initMGraph() {
    for( int i = 0; i < MAX; i++ )
        for( int j = 0; j < MAX; j++ ) {
            if( i == j ) MGraph[i][j] = 0;
            else MGraph[i][j] = INF;
        }
}

void insertEdge( int a, int b, int w ) {
    MGraph[a][b] = w;
    MGraph[b][a] = w;
}

/* Prim最小生成树算法 */

int prim() {
    int ans = 0;
    // 默认从0号顶点开始进行算法
    for( int i = 0; i < N; i++ ) {
        dist[i] = MGraph[0][i];
    }

    parent[0] = -1;
    dist[0] = 0;

    int min, v;
    int cnt = 1;
    while( 1 ) {
        min = INF;
        v = -1;
        for( int i = 0; i < N; i++ ) {
            if( dist[i] != 0 && dist[i] < min ) {
                min = dist[i];
                v = i;
            }
        }

        if( v == -1 ) break;

        ans = ans + min;
        dist[v] = 0;
        cnt++;
        for( int i = 0; i < N; i++ ) {
            if( MGraph[v][i] != INF && dist[i] != 0 ) {
                if( MGraph[v][i] < dist[i] ) {
                    dist[i] = MGraph[v][i];
                    parent[i] = v;
                }
            }
        }
    }

    //printf( "%d\n", cnt );
    if( cnt < N ) {
        return -1;
    }

    return ans;
}


void initSet() {
    for( int i = 0; i < N; i++ )
        father[i] = i;
}

int findFather( int x ) {
    if( father[x] == x ) return x;
    else return findFather( father[x] );
}

bool Union( int a, int b ) {
    int fatherA = findFather( a );
    int fatherB = findFather( b );
    if( fatherA == fatherB ) return false;
    else father[fatherA] = father[b];
    return true;
}

int cmp( Edge a, Edge b ) {
    return a.weight < b.weight ? 1 : 0;
}

int Kruskal() {
    initSet();
    sort( edge, edge + M, cmp );
    int cnt = N;
    int ans = 0;
    for( int i = 0; i < M && cnt > 1; i++ ) {
        if( Union( edge[i].start, edge[i].end ) ) {
            ans = ans + edge[i].weight;
            cnt--;
        }
    }
    //printf( "%d\n", cnt );
    if( cnt > 1 ) {
        ans = -1;
    }
    return ans;
}

int main() {
    initMGraph();
    //freopen( "123.txt", "r", stdin );
    scanf( "%d%d", &N, &M );

    int a, b, w;
    for( int i = 0; i < M; i++ ) {
        scanf( "%d%d%d", &a, &b, &w );
        insertEdge( a - 1, b - 1, w );
        edge[i].weight = w;
        edge[i].start = a - 1;
        edge[i].end = b - 1;
    }

    //int ans = prim();
    int ans = Kruskal();
    printf( "%d", ans );
    return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值