#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
const int maxint=99999;
struct yuandian
{
int stationId;
double cloestDist,averageDist;
}Hxd[15];
int N,M,K,D,hxdIndex=0;
int G[1024][1024]; //矩阵表示图
bool s[1024]; //S集合
double dist[1024]; //dist数组(当前状态下源点到其他所有点的最短路径)
int cmp(yuandian a,yuandian b)
{
if(a.cloestDist==b.cloestDist)
{
if(a.averageDist==b.averageDist)
return a.stationId<b.stationId;
else
return a.averageDist<b.averageDist;
}
else
return a.cloestDist>b.cloestDist;
}
void Dijkstra(int v)
{
//初始化
for(int i=1;i<=N+M;i++)
{
dist[i]=G[v][i];
s[i]=false;
}
//将源点放入S集合
s[v]=true;
dist[v]=0;
//将剩下的点放入S集合
for(int i=2;i<=N+M;i++)
{
//找到一个点放入集合S
int u;
double mindist=maxint;
for(int j=1;j<=N+M;j++)
{
if(s[j]==false&&dist[j]<mindist)
{
mindist=dist[j];
u=j;
}
}
s[u]=true;
//更新dist数组
for(int j=1;j<=N+M;j++)
if(s[j]==false&&G[u][j]!=maxint&&dist[u]+G[u][j]<dist[j])
dist[j]=dist[u]+G[u][j];
}
//本题逻辑
Hxd[hxdIndex].cloestDist=dist[1];
double sum=0;
for(int i=1;i<=N;i++)
{
sum+=dist[i];
if(dist[i]>D)
return;
if(dist[i]<Hxd[hxdIndex].cloestDist)
Hxd[hxdIndex].cloestDist=dist[i];
}
Hxd[hxdIndex].averageDist=sum/N;
Hxd[hxdIndex].stationId=v;
hxdIndex++;
}
int main()
{
for(int i=1;i<1024;i++)
for(int j=1;j<1024;j++)
if(i==j)
G[i][j]=0;
else
G[i][j]=maxint;
scanf("%d%d%d%d",&N,&M,&K,&D);
string a,b,c;
for(int i=1;i<=K;i++)
{
cin>>a>>b>>c;
int num1,num2;
if(a[0]=='G')
num1=N+atoi(a.substr(1).c_str());
else
num1=atoi(a.c_str());
if(b[0]=='G')
num2=N+atoi(b.substr(1).c_str());
else
num2=atoi(b.c_str());
G[num1][num2]=G[num2][num1]=atoi(c.c_str());
}
//Dijkstra算法
for(int i=N+1;i<=N+M;i++)
Dijkstra(i);
sort(Hxd,Hxd+hxdIndex,cmp);
if(hxdIndex!=0)
printf("G%d\n%.1lf %.1lf",Hxd[0].stationId-N,Hxd[0].cloestDist,Hxd[0].averageDist);
else
printf("No Solution");
return 0;
}
这题显然是要求解图的某个点到图的所有其他点的最短距离,因此不难想到Dijkstra算法,题目的细节挺多,要仔细地做。
在输入的处理上,我用string接受输入,判断是否是候选点(候选点均为G开头),把形如G1,G2...GM的候选点转换成数字(这与house的数量有关,
如G1=house的总数量+1,以此类推),建图之后从第一个候选点开始调用Dijkstra算法,每次运算完毕都会得到一个dist数组,表示了从这个候选点
到其他所有house的最短距离,再按照题意完成相应的处理,保存在结构体数组中。
最后对这个结构体数组进行排序,优先级如下:
1.距离当前候选点最近的house的距离 大者优先
2.当前候选点与house的平均距离 小者优先
3.当前候选点的编号 小者优先
做这题之前没有认认真真地学一遍Dijkstra算法,现在总算是掌握了。
回忆一次Dijkstra算法的思路:
Dijkstra算法主要维护一个S集合和一个U集合,S集合表示已经求出最短路径的点,U集合表示还未求出最短路径的点,Dijkstra的过程就是将U集合中的点慢慢
地加入到S集合中,在这个过程中源点到所有其他点的距离就被求出来了,如何从U集合中选择恰当的点是Dijkstra算法的关键,挑选的依据是dist[]数组,这个
数组表示当前状态下源点到其他点的最短路径,每次选择就选U集合中的与源点的最短路径最小的那个点,加入S集合后,刚加入的点与源点的最短距离就已经
定下了,那么以这个点为中间点,再次更新dist数组,得到新的最短路径,如此反复,便可求出所有点到源点的最短路径。