POJ 1789 (最小生成树 Prim)

题目描述:给予n个长度为7的字符串,定义两字符串间的代价为同一位置不同的字符的个数,现在要联通所有的字符串求最小代价。
    思路:一开始使用Krustal算法,然而因为是稠密图导致TLE,换用Prim。

Krustal:(TLE)

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <queue>
#define N 2005
using namespace std;
struct e{
    int fi,sec,val;
    e(){}
    e(int a,int b,int c):fi(a),sec(b),val(c){}
    bool operator<(const e&X)const{
        return val>X.val;
    }
};
class graph{
    int n;
    char str[N][8];
    int belong[N];
    priority_queue<e>edge;
    int check(char *a,char *b){
        int cnt = 0;
        char *e = a+7;
        while (a!=e){
            if(*a!=*b)cnt++;
            a++,b++;
        }
        return cnt;
    }
    int find(int x){
        return x==belong[x]?x:belong[x] = find(belong[x]);
    }
    bool UNION(int a,int b){
        int x = find(a);
        int y = find(b);
        if(x!=y){
            belong[y] = x;
            return true;
        }
        else return false;
    }
public:
    int init(){
        cin>>n;
        for(int i = 1 ; i <= n ; ++i){
            scanf("%s",str[i]);
            belong[i] = i;
        }
        return n;
    }
    void build(){
        for(int i = 1 ; i < n ; ++i){
            for(int j = i+1 ; j <= n ; ++j){
                edge.push(e(i,j,check(str[i],str[j])));
            }
        }
    }
    int get_ans(){
        int x,y;
        e tmp;
        int ans = 0;
        while (!edge.empty()){
            tmp = edge.top();
            edge.pop();
            if(UNION(tmp.fi,tmp.sec)){
                ans+=tmp.val;
            }
        }
        return ans;
    }
};
graph ss;
int main(){
    while (ss.init()){
        ss.build();
        cout<<"The highest possible quality is 1/";
        cout<<ss.get_ans()<<".\n";
    }
}

Prim(AC):

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <queue>
#include <cstring>

#define N 2005
using namespace std;
class graph{
    int n;
    char str[N][8];
    int plant[N][N],dis[N];
    bool inset[N];
    int check(char *a,char *b){
        int cnt = 0;
        char *e = a+7;
        while (a!=e){
            if(*a!=*b)cnt++;
            a++,b++;
        }
        return cnt;
    }

public:
    int init(){
        cin>>n;
        for(int i = 1 ; i <= n ; ++i){
            scanf("%s",str[i]);
        }
        return n;
    }
    void build(){
        for(int i = 1 ; i < n ; ++i){
            for(int j = i+1 ; j <= n ; ++j){
                plant[i][j] = plant[j][i] = check(str[i],str[j]);
            }
        }
    }
    int get_ans(){
        int ans = 0;
        memset(inset,0, sizeof(inset));
        memset(dis,0x3f3f3f3f, sizeof(dis));
        dis[1] = 0;
        for(int i = 1 ; i <= n ; ++i){
            int mark = 0;
            for(int j = 1 ; j <= n ; ++j){
                if(!inset[j])
                    if(!mark)mark = j;
                else if(dis[j]<dis[mark])mark = j;
            }
            if(!mark)break;
            inset[mark] = true;
            ans+=dis[mark];
            for(int j = 1 ; j <= n ; ++j){
                if(!inset[j]){
                    dis[j] = min(dis[j],plant[mark][j]);
                }
            }
        }
        return ans;
    }
};
graph ss;
int main(){
    while (ss.init()){
        ss.build();
        cout<<"The highest possible quality is 1/";
        cout<<ss.get_ans()<<".\n";
    }
}
//在稠密图中比较实用,每次找出距离最小的点加入集合,然后更新剩下不在集合中的点的最小距离(只用以新加入的点做参考)
//答案正确 内存使用:16192KB 运行时间:422ms

 

posted @ 2018-08-01 23:07  DevilInChina  阅读(212)  评论(0编辑  收藏  举报