poj1789 最小生成树

题目链接在这里

题目大意:

有n辆卡车,每个卡车有一个编号,编号由七个字母组成。卡车之间的距离是两车字母不同的数量。让你选择一种方式将卡车连起来,使他们的距离总和最小。

思路分析:

先暴力求出每个卡车之间的距离,然后建立最小生成树就好。

代码如下:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>
#define rep(i, x) for(int i = 0; i < x; ++i)
#define clr(x) memset(x, 0, sizeof(x))
using namespace std;
const int MaxN = 2005;

struct Edge{
    int x, y, val;
    bool operator < (const Edge &e) const{
        return val > e.val;
    }
};

int n;
char str[MaxN][8];
int r[MaxN], par[MaxN];

int getDis(char *p, char *q){
    int val = 0;
    rep(i, 7){
        if(*p != *q){
            ++val;
        }
        ++p;
        ++q;
    }
    return val;
}

void init(){
    clr(r);
    rep(i, MaxN)    par[i] = i;
}

int Find(int x){
    if(x == par[x]) return x;
    return par[x] = Find(par[x]);
}

void unite(int x, int y){
    x = Find(x);
    y = Find(y);
    if(x == y)  return ;
    if(r[x] < r[y]) par[x] = y;
    else{
        par[y] = x;
        if(r[x] == r[y])    ++r[x];
    }
}

bool check(int x, int y){
    return Find(x) == Find(y);
}

void solve(){
    priority_queue<Edge> que;
    rep(i, n){
        rep(j, i){
            int val = getDis(str[i], str[j]);
            //printf("x:%d, y:%d, val:%d\n", i, j, val);
            que.push(Edge{i, j, val});
        }
    }
    int ans = 0;
    while(--n){
        Edge e = que.top();
        que.pop();
        if(check(e.x, e.y)){
            ++n;
            continue;
        }
        ans += e.val;
        unite(e.x, e.y);
    }
    printf("The highest possible quality is 1/%d.\n", ans);
}

int main(){
    while(~scanf("%d", &n) && n){
        init();
        rep(i, n){
            scanf("%s", str[i]);
        }
        solve();
    }
}

猜你喜欢

转载自blog.csdn.net/Never__Give_Up_/article/details/86550291