poj 1251 Jungle Roads(最小生成树)

一看就是最小生成树

图论很久没看了,想抽时间系统地看下

所以直接把以前的模板贴上了

题目有陷阱就是读入字符如果用scanf来做会很恶心

因为每一行末尾可能有多个空格,只用getchar()会RE

所以直接用cin处理即可

代码如下:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAXN 1010
#define INF 0x7fffffff
#define ll long long
using namespace std;

int map[MAXN][MAXN];
int dis[MAXN];
int n;

int prim(void){
    int now;
    int minedge,minnode;
                   
    for(int i=0;i<n;i++)
        dis[i] = INF;
    now = 0;
    int ans = 0;
    for(int i=0; i<n-1; i++){
        dis[now] = -1;
        minedge = INF;
        for(int j=0; j<n; j++) {
            if(j!=now && dis[j]>=0) {
                if(map[now][j] > 0) {
                    dis[j] = min(dis[j], map[now][j]);
                }
                if(dis[j] < minedge) {
                    minedge = dis[j];
                    minnode = j;       
                }        
            }           
        }
        now = minnode;
        ans += minedge;                     
    }
    return ans;
}


int main(void) {
    int t, x, y, dis;
    char ch;
    while(cin >> n, n) {
        memset(map, 0, sizeof(map));
        for(int c=0; c<n-1; ++c) {
            cin >> ch;
            x = ch-'A';
            cin >> t; 
            for(int i=0; i<t; ++i) {
                cin >> ch >> dis;
                y = ch-'A';
                map[x][y] = dis;
                map[y][x] = dis;
            }
        }
    /*
        for(int i=0; i<n; ++i) {
            for(int j=0; j<n; ++j) {
                if(map[i][j]) {
                    printf("map[%c][%c] = %d\t", i+'A', j+'A', map[i][j]);
                }
            }
            printf("\n");
        }
    */
        printf("%d\n", prim());
    }
    return 0;
}

刚刚在练习克鲁斯卡尔算法,对着模板写了下,把代码也贴在这吧

#include <cstdio>
#include <iostream>
#include <algorithm>
#define MAXN 1010
#define ll long long
using namespace std;

int u[MAXN], v[MAXN], w[MAXN];
int p[MAXN], r[MAXN];
int n, m, cnt;

int cmp(const int i, const int j) {
    return w[i]<w[j];
}

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

int Kruskal() {
    int ans = 0;
    for(int i=0; i<n; ++i)
        p[i] = i;
    for(int i=0; i<cnt; ++i)
        r[i] = i;
    sort(r, r+cnt, cmp);
    for(int i=0; i<cnt; ++i) {
        int e = r[i];
        int x = find(u[e]);
        int y = find(v[e]);
        if(x != y) {
            ans += w[e];
            p[x] = y;
        }
    }
    return ans;
}

int main(void) {
    char ch1, ch2;
    while(scanf("%d", &n), n) {
        cnt = 0;
        for(int i=0; i<n-1; ++i) {
            getchar();
            ch1 = getchar();
            scanf("%d", &m);
            while(m--) {
                getchar();
                ch2 = getchar();
                u[cnt] = ch1-'A';
                v[cnt] = ch2-'A';
                scanf("%d", &w[cnt]);
                cnt++;
            }
        }
        cout << Kruskal() << endl;
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值