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

原文地址:https://www.cnblogs.com/DevilInChina/p/9404539.html

时间: 2024-11-06 03:35:11

POJ 1789 (最小生成树 Prim)的相关文章

poj 1789 最小生成树 kruskal实现

题目链接:http://poj.org/problem?id=1789 1Y 题目大意:对于每一个点给你一个字符串,两个点之间的距离就是两个点所对应的字符串对应位置有几个不同的字符..找出最小生成树. 把Kruskal换成了用一个struct来记录边的两个点,以及这条边的距离.这样就不需要多开一个数组... 之后用一个结构体排序,让长度最小的边排到最前面.. 代码: #include <iostream> #include <cstdio> #include <cstring

POJ - 2421(最小生成树.prim)

题目: 题目链接: http://poj.org/problem?id=2421 Constructing Roads Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 27947 Accepted: 12316 Description There are N villages, which are numbered from 1 to N, and you should build some roads such that e

POJ 1789 -- Truck History(Prim)

 POJ 1789 -- Truck History Prim求分母的最小.即求最小生成树 1 #include<iostream> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const int maxn = 2000 + 10; 6 const int INF = 1000000; 7 int n;//有几个卡车 8 char str[maxn][10]; 9 int d[ma

POJ 2485-Highways(最小生成树prim)

Highways Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 22433   Accepted: 10341 Description The island nation of Flatopia is perfectly flat. Unfortunately, Flatopia has no public highways. So the traffic is difficult in Flatopia. The Fl

Kuskal/Prim POJ 1789 Truck History

题目传送门 1 /* 2 题意:给出n个长度为7的字符串,一个字符串到另一个的距离为不同的字符数,问所有连通的最小代价是多少 3 Kuskal/Prim: 先用并查集做,简单好写,然而效率并不高,稠密图应该用Prim.这是最小生成数的裸题,然而题目有点坑爹:( 4 */ 5 #include <cstdio> 6 #include <cstring> 7 #include <string> 8 #include <algorithm> 9 #include

POJ 1258 Agri-Net (最小生成树+Prim)

Agri-Net Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 39820   Accepted: 16192 Description Farmer John has been elected mayor of his town! One of his campaign promises was to bring internet connectivity to all farms in the area. He nee

poj 1258 Agri-Net (最小生成树 prim)

Agri-Net Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 39499   Accepted: 16017 Description Farmer John has been elected mayor of his town! One of his campaign promises was to bring internet connectivity to all farms in the area. He nee

POJ 1258 Agri-Net (prim最小生成树)

最小生成树模板题 #include<bits/stdc++.h> using namespace std; int n,a; int dist[120],m[120][120]; void prim() {     bool p[1020];     for(int i=2;i<=n;i++)     {         p[i]=false;         dist[i]=m[1][i];     }     dist[1]=0,p[1]=true;     for(int i=1;

poj 1789 Truck History 解题报告

题目链接:http://poj.org/problem?id=1789 题目意思:给出 N 行,每行7个字符你,统计所有的 行 与 行 之间的差值(就是相同位置下字母不相同),一个位置不相同就为1,依次累加.问最终的差值最少是多少. 额.....题意我是没看懂啦= =......看懂之后,就转化为最小生成树来做了.这是一个完全图,即每条边与除它之外的所有边都连通.边与边的权值是通过这个差值来算出来的. 1 #include <iostream> 2 #include <cstdio>