#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數組,得到新的最短路徑,如此反覆,便可求出所有點到源點的最短路徑。