题目大意:有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;
}
}