校内训练0611 最近点对
【题目大意】
n个点m条边带权无向图,求前k个点之间的最短距离,多组数据。
T<=10,n<=50000,k<=1000
【题解】
首先暴力O(Tknlogn)是过不了的。。。
考虑比暴力优秀一点的做法?随机化!
我们随机一半的点分在A,一半的点分在B,S向A中点连边,边权0;B中点想T连边,边权0.
每次求S->T的最短路对应的就是A点集->B点集的最短路。
多随机几次就行了。
标程0.5s,标准时限1.5s
本机标程2s,仿照开3倍时限,开到6s,过了。。
复杂度O(T*nT*nlogn),nT为随机次数,我取了5,本机太慢了qwq
# include <queue> # include <stdio.h> # include <string.h> # include <iostream> # include <algorithm> // # include <bits/stdc++.h> using namespace std; typedef long long ll; typedef long double ld; typedef unsigned long long ull; const int M = 4e5 + 10; const int mod = 1e9+7, INF = 1e9; # define RG register # define ST static int n, m, K, S, T, id[M], old[M]; int head[M], nxt[M], to[M], w[M], tot=0; inline void add(int u, int v, int _w) { ++tot; nxt[tot] = head[u]; head[u] = tot; to[tot] = v; w[tot] = _w; } inline void adde(int u, int v, int _w) { add(u, v, _w); add(v, u, _w); } struct pa { int x, dis; pa() {} pa(int x, int dis) : x(x), dis(dis) {} friend bool operator < (pa a, pa b) { return a.dis > b.dis; } }; int d[M]; bool vis[M]; priority_queue< pa > q; inline int dijkstra() { for (int i=1; i<=T; ++i) d[i] = INF, vis[i] = 0; q.push(pa(S, 0)); d[S] = 0; while(!q.empty()) { pa t = q.top(); q.pop(); if(vis[t.x]) continue; vis[t.x] = 1; for (int i=head[t.x]; i; i=nxt[i]) { if(d[to[i]] > d[t.x] + w[i]) { d[to[i]] = d[t.x] + w[i]; q.push(pa(to[i], d[to[i]])); } } } return d[T]; } inline void sol() { cin >> n >> m >> K; for (int i=1, u, v, _w; i<=m; ++i) { scanf("%d%d%d", &u, &v, &_w); adde(u, v, _w); } for (int i=1; i<=K; ++i) id[i] = i; for (int i=1; i<=K; ++i) old[i] = head[i]; int nTOT = tot; S = n+1, T = n+2; int ans = INF; for (int Test=1; Test<=5; ++Test) { random_shuffle(id+1, id+K+1); for (int i=1; i<=K/2; ++i) adde(S, id[i], 0); for (int i=K/2+1; i<=K; ++i) adde(id[i], T, 0); ans = min(ans, dijkstra()); for (int i=1; i<=K; ++i) head[i] = old[i]; tot = nTOT; head[S] = head[T] = 0; } cout << ans << endl; tot = 0; for (int i=1; i<=n+2; ++i) head[i] = 0; } int main() { freopen("nearest.in", "r", stdin); freopen("nearest.out", "w", stdout); int T; cin >> T; while(T--) sol(); return 0; }