这题就是一个多源的最短路径问题: 先计算出当前已经放好的消防站所对应的各个房子到消防站的最短距离, 然后枚举新的一个消防站应该排放的位置,然后选择这些位置中的最优解。 在这里就用了比较简单的Dijkstra水过~ #include<stdio.h> #include<string.h> #include<limits.h> const int maxn = 510; int g[maxn][maxn]; int fire[maxn]; int f, n; char input[maxn]; int d[maxn]; int dis[maxn]; int tmp[maxn]; bool vis[maxn]; int ans, ansi; void init() { for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) if(i == j) g[i][j] = 0; else g[i][j] = INT_MAX; } void dijkstra(int s) { memset(vis, false, sizeof(vis)); for(int i = 1; i <= n; i++) d[i] = (i == s ? 0 : INT_MAX); for(int i = 1; i <= n; i++) { int x, m = INT_MAX; for(int y = 1; y <= n; y++) if(!vis[y] && d[y] <= m) m = d[x = y]; vis[x] = true; for(int y = 1; y <= n; y++) if(g[x][y] < INT_MAX && d[x] + g[x][y] < d[y]) d[y] = d[x] + g[x][y]; } for(int i = 1; i <= n; i++) if(dis[i] > d[i]) dis[i] = d[i]; } //#define LOCAL int main() { #ifdef LOCAL freopen("input.txt", "r", stdin); freopen("output.txt", "w", stdout); #endif int test; scanf("%d", &test); for(int t = 0; t < test; t++) { if(t) printf("/n"); scanf("%d%d", &f, &n); init(); for(int i = 0; i < f; i++) scanf("%d", &fire[i]); int a, b, c; getchar(); while(gets(input)) { if(strcmp(input, "") == 0) break; sscanf(input, "%d%d%d", &a, &b, &c); if(c < g[a][b]) g[a][b] = g[b][a] = c; } ans = INT_MAX; ansi = 1; for(int i = 1; i <= n; i++) dis[i] = INT_MAX; for(int j = 0; j < f; j++) dijkstra(fire[j]); for(int i = 1; i <= n; i++) { fire[f] = i; memcpy(tmp, dis, sizeof(dis)); dijkstra(fire[f]); int max = -INT_MAX; for(int j = 1; j <= n; j++) if(max < dis[j]) max = dis[j]; if(ans > max) { ans = max; ansi = i; } memcpy(dis, tmp, sizeof(tmp)); } printf("%d/n", ansi); } return 0; }