FZU - 2254 英语考试 (最小生成树)

题意:给你n个串,每个串长度不超过10。小明想联想记单词,如果对两个词进行联想记忆 花费 w*k (w为给定值,k为字符串之间对应位置不同的个数)。当然也可以不联想记忆,这样就只花费字符串长度的体力

问记忆完所有单词花费最小体力。

思路:把每个串当作一个结点,不同联想记忆的花费为路径权值(要将w*k与 串本身长度进行比较选最小作为权值),然后跑一遍prim算法即可

完整代码:

#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
#include <string>
#include <queue>
using namespace std;
typedef pair<int,int> pii;
const int maxm = 1e6+10;
const int inf = 0x3f3f3f3f;
const int maxn = 1e3+5;
int top;
int n,m,cost;
int ans;
string s[maxn];
int head[maxn];
int vis[maxn];
int dist[maxn];
//堆重载 
struct cmp{
    bool operator() (pii a, pii b){
        return a.first>b.first;
    }
};
struct Edge{
    int u,v,w;
    int next;
}edge[maxm];

void init(){
    memset(head,-1,sizeof(head));
    memset(edge,0,sizeof(edge));
    memset(dist,-1,sizeof(dist));
    memset(vis,0,sizeof(vis));
    top = 0;
    ans = 0;
}
void add(int v,int u,int w){
    edge[top].u = u;
    edge[top].v = v;
    edge[top].w = w;
    edge[top].next = head[u];
    head[u] = top++;
}
void prim(int s){
    int i;
    priority_queue<pii,vector<pii> ,cmp>Q;
    dist[s] = 0;
    vis[s] = 1;
    for(i = head[s]; ~i; i = edge[i].next){
        //先把到起点边的距离初始化为其本身 
        dist[edge[i].v] = edge[i].w;
        Q.push(make_pair(dist[edge[i].v],edge[i].v));
    }
    while(!Q.empty()){
        pii t = Q.top();
        Q.pop();
        if(vis[t.second]) continue;
        ans += t.first;
        vis[t.second] = 1;
        for(i = head[t.second]; ~i ;i = edge[i].next){
            int j = edge[i].v;
            //没被访问没有连接或者权值太小 
            if(!vis[j]&&(dist[j]>edge[i].w||dist[j]==-1)){
                dist[j] = edge[i].w;
                Q.push(make_pair(dist[j],j));
            }
        }
    }
}
int getCost(int i,int j){
    int res = 0;
    for(int k=0;k<m;k++){
        if(s[i][k]!=s[j][k]) res++;    
    }
    return res;
}
int main(){
    while(cin>>n>>m>>cost){
        init();
        for(int i =0 ;i<n;i++) cin>>s[i];
           for(int i = 0;i<n;i++){
               for(int j = 0;j<n;j++){
                   if(i==j) continue;
                   int c = min(cost*getCost(i,j),m); 
                   add(i,j,c);        
            }    
        }
        prim(0);
        cout<<ans+m<<endl;
    }
}

猜你喜欢

转载自www.cnblogs.com/Tianwell/p/11347952.html