- 记录以字符串形式读入,再转换为数字
- n间房子,m个气站,共n+m个点
- 循环Dijkstra得出 Gi 的最短距离,枚举判断是否有房子超过了覆盖范围,同时计算最小距离和平均距离
- 题设要求的是求最小距离中的最大值
#include <cstdio>
#include <vector>
#include <map>
#include <cstring>
#include <algorithm>
#include <queue>
#include <functional>
using namespace std;
const int maxn = 1100, inf = 999999999;
int n, m, k, maxd;
int best = 0, mind = -1;
double average = 999999999;
int G[maxn][maxn], d[maxn];
bool vis[maxn] = {false};
typedef pair<int, int> P;
vector<int> pre[maxn], path, temp;
priority_queue<P, vector<P>, greater<P> > pq;
void Dijkstra(int s) {
memset(vis, 0, sizeof(vis));
fill(d, d+maxn, inf);
P p;
int u;
d[s] = 0;
vis[s] = true;
while(!pq.empty()) pq.pop();
pq.push(P(0, s));
while(!pq.empty()) {
p = pq.top();
pq.pop();
u = p.second;
if(p.first > d[u]) continue;
vis[u] = true;
for(int v = 1; v <= n + m; v++) {
if(vis[v] == false && G[u][v] != inf) {
if(d[v] > d[u] + G[u][v]) {
d[v] = d[u] + G[u][v];
pq.push(P(d[v], v));
pre[v].clear();
pre[v].push_back(u);
} else if (d[v] == d[u] + G[u][v]) {
pre[v].push_back(u);
}
}
}
}
}
int getID(char str[]) {
int i = 0, len = strlen(str), ID = 0;
while(i < len) {
if(str[i] != 'G') {
ID = ID * 10 +(str[i] - '0');
}
i++;
}
if(str[0] == 'G') return n + ID;
else return ID;
}
int main() {
fill(G[0], G[0] + maxn*maxn, inf);
scanf("%d%d%d%d", &n, &m, &k, &maxd);
int dis;
char c1[5], c2[5];
for(int i = 0; i < k; i++) {
scanf("%s %s %d", &c1, &c2, &dis);
int u = getID(c1);
int v = getID(c2);
G[u][v] = G[v][u] = dis;
}
for(int i = n + 1; i <= n + m; i++) {
Dijkstra(i);
int dist = inf;
double avg = 0;
for(int j = 1; j <= n; j++) {
if(d[j] > maxd) {
dist = -1;
break;
}
if(d[j] < dist) dist = d[j];
avg += 1.0 * d[j] / n;
}
if(dist == -1) continue;
if(dist > mind) {
mind = dist;
best = i;
average = avg;
}else if (dist == mind && avg < average) {
best = i;
average = avg;
}
}
if(best == 0) {
printf("No Solution\n");
} else {
printf("G%d\n", best - n);
printf("%d.0 %.1f\n", mind, average);
}
return 0;
}