POJ 1251 优先队列+prim

题目链接

题目大意:有n个村庄,每个村庄最多有15条路,并且村庄用字母表示,且由小到大给出,求最小的联通路径的花费

 

这是一道典型的最短路的模板题,在这里我就不用模板去写了,熟悉一下prim的队列优化来做

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<queue>
#include<algorithm>
using namespace std;
const int INF=0x3f3f3f3f;
int e[30][30];//记录地图
bool vis[30];//标记哪些点没有走过
int dis[30];
int n;
struct node
{
    int v;//表示当前v这个点离树最近
    int len;//最近的长度是多少
    bool operator<(const node &b)const//将优先队列改成最小堆
    {
        return len>b.len;
    }
};
priority_queue<node>q;
int main()
{
    ios::sync_with_stdio(0);cin.tie(0);
    while(cin>>n&&n)
    {
        memset(e,INF,sizeof e);
        memset(vis,0,sizeof vis);
        int m=n;
        for(int i=0;i<n-1;i++)
        {
            e[i][i]=0;e[i+1][i+1]=0;
            char str0[5];
            char str1[5];
            int k,x;cin>>str0>>k;
            while(k--)
            {
                cin>>str1>>x;
                e[str0[0]-'A'+1][str1[0]-'A'+1]=x;
                e[str1[0]-'A'+1][str0[0]-'A'+1]=x;
            }
        }
        memset(dis,INF,sizeof dis);//一开始就将其全部最大化,这里的dis不是最短路里面一个点到另一个点的
        //最短路径,这里的意思是到这棵最小生成树的最短路径,这点要明白
            int ans=0;
            node now;
            now.v=1;now.len=0;//先将第一个点,也就是它本身放入队列(其实先放哪一个都行)
            q.push(now);
           while(q.size())
           {
               now=q.top();q.pop();
               if(vis[now.v]) continue;
               vis[now.v]=1;//此时找到了当前的最短路,标记一下是哪个点最近,将其距离加上
               ans+=now.len;
               for(int i=1;i<=n;i++)
               {
                   if(!vis[i]&&e[now.v][i]<dis[i])
                   {
                       node next;
                       next.v=i;
                       next.len=e[now.v][i];
                       dis[i]=e[now.v][i];
                       q.push(next);
                   }
               }
           }
            cout<<ans<<endl;
           }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值