这题不错
反正我想了一天是没想出来hhhh
后来看了糖老师的题解 恍然大悟
设 dis[i][j],dis′[i][j] 分别为原图和新图中i到j的最短路径。
设新加的一个点为x
若要使在新图中最短路不经过x,应要满足
∀u,dis′[u][x]>=max{∣dis[u][1]−dis′[x][1]∣,∣dis[u][2]−dis′[x][2]∣}
这个还是能想得到的
得到了这个以后,因为要使 ∑dis′[u][x] 最小,故应该取等号。把这个式子写出来,就会是
∑max{∣dis[u][1]−dis′[x][1]∣,∣dis[u][2]−dis′[x][2]∣}
如果把每个 (dis[u][1],dis[u][2]) 看做一个点,答案就是是这些点到点 (dis′[x][1],dis′[x][2]) 的切比雪夫距离和的最小值。
于是就乱搞咯2333
用dijkstra,时间复杂度 O(m+nlogn) 。亲测SPFA会TLE,不知道是不是姿势问题。
#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=a;i>=b;i--)
#define fore(i,u) for(int i=head[u];i;i=nxt[i])
#define cr(x) memset(x , 0 , sizeof x)
#define pii pair<ll , int>
#define mp make_pair
#define maxn 100003
#define maxm 600007
inline int rd() {
char c = getchar();
while (!isdigit(c)) c = getchar() ; int x = c - '0';
while (isdigit(c = getchar())) x = x * 10 + c - '0';
return x;
}
typedef long long ll;
typedef int arr_int[maxn];
typedef ll arr_ll [maxn];
typedef int adj[maxm];
const ll inf = 1e12;
arr_int head , vis;
arr_ll dis[2] , x , y;
adj to , val , nxt;
int n , m , ett;
priority_queue<pii , vector<pii> , greater<pii> > Q;
inline void ins(int u , int v , int w) {
to[++ ett] = v , val[ett] = w , nxt[ett] = head[u] , head[u] = ett;
}
void input() {
n = rd() , m = rd();
cr(head) , ett = 0;
rep (i , 1 , m) {
int u = rd() , v = rd() , w = rd();
ins(u , v , w) , ins(v , u , w);
}
}
void dijk(int s) {
int c = s - 1;
rep (i , 1 , n) dis[c][i] = inf;
cr(vis);
dis[c][s] = 0;
Q.push(mp(0 , s));
while (!Q.empty()) {
int u = Q.top().second ; Q.pop();
if (vis[u]) continue;
vis[u] = 1;
fore (i , u) {
int v = to[i] , w = val[i];
if (dis[c][v] > dis[c][u] + w) {
dis[c][v] = dis[c][u] + w;
Q.push(mp(dis[c][v] , v));
}
}
}
}
void solve() {
dijk(1) , dijk(2);
rep (i , 1 , n) {
x[i] = dis[0][i] + dis[1][i];
y[i] = dis[0][i] - dis[1][i];
}
sort(x + 1 , x + n + 1) , sort(y + 1 , y + n + 1);
ll nx = x[(n + 1) / 2] , ny = y[(n + 1) / 2];
double ans = 0;
rep (i , 1 , n)
ans += abs(x[i] - nx) + abs(y[i] - ny);
printf("%.12lf\n" , ans / (2.0 * n));
}
int main() {
#ifndef ONLINE_JUDGE
freopen("data.txt" , "r" , stdin);
#endif
int T = rd();
rep (i , 1 , T) {
input();
solve();
}
return 0;
}