CF266D BerDonalds

SP1479 PT07C - The GbAaY Kingdom

SP735 MDST - Minimum Diameter Spanning Tree

需要注意的是,EvaDiaCen 函数中有整形除以二的操作,所以需要保证初始时所有边权为二的倍数,需要在读入时将边权乘二,输出时除回去就行了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
int n, m;
struct Edge {
int u, v, w;
} eg[MAXm + 10];

int dis[MAXn + 10][MAXn + 10];
void Floyd() {
for (int k = 1; k <= n; ++k) {
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= n; ++j) {
dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);
}
}
}
}
pair<int, int> tmp[MAXn + 10];
int rk[MAXn + 10][MAXn + 10];
void EvaRk() {
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= n; ++j) {
tmp[j] = make_pair(dis[i][j], j);
}
sort(tmp + 1, tmp + 1 + n);
for (int j = 1; j <= n; ++j) {
rk[i][j] = tmp[j].second;
}
}
}
int dia;
int cenu, cenv, cendisu, cendisv;
void EvaDiaCen() {
dia = INF;
for (int i = 1; i <= m; ++i) {
int u = eg[i].u, v = eg[i].v, w = eg[i].w;
int mxdisv = dis[v][rk[u][n]];
for (int j = n - 1; j; --j) {
if (mxdisv <= dis[v][rk[u][j]]) {
if (dia > dis[u][rk[u][j]] + mxdisv + w) {
dia = dis[u][rk[u][j]] + mxdisv + w;
cenu = u;
cenv = v;
cendisu = dia / 2 - dis[u][rk[u][j]];
cendisv = dia / 2 - mxdisv;
}
mxdisv = dis[v][rk[u][j]];
}
}
}
}
bool vis[MAXn + 10];
int dist[MAXn + 10], from[MAXn + 10];
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
void Dijkstra(int s) {
memset(dist, 0x3f, sizeof(dist));
dist[s] = 0;
pq.push(make_pair(0, s));
while (!pq.empty()) {
int cur = pq.top().second; pq.pop();
if (vis[cur]) continue;
vis[cur] = 1;
for (int i = head[cur]; i; i = nex[i]) {
if (vis[to[i]]) continue;
if (dist[to[i]] > dist[cur] + wei[i]) {
dist[to[i]] = dist[cur] + wei[i];
from[to[i]] = cur;
pq.push(make_pair(dist[to[i]], to[i]));
}
}
}
}
int cntmdst; pair<int, int> mdst[MAXm + 10];
void EvaMdst() {
for (int i = 1; i <= m; ++i) {
if (eg[i].u == cenu && eg[i].v == cenv) continue;
Insert(eg[i].u, eg[i].v, eg[i].w);
Insert(eg[i].v, eg[i].u, eg[i].w);
}
Insert(n + 1, cenu, cendisu);
Insert(cenu, n + 1, cendisu);
Insert(n + 1, cenv, cendisv);
Insert(cenv, n + 1, cendisv);
Dijkstra(n + 1);
for (int i = 1; i <= n; ++i) {
if (i == cenu || i == cenv) continue;
mdst[++cntmdst] = make_pair(i, from[i]);
}
mdst[++cntmdst] = make_pair(cenu, cenv);
}

signed main() {
// ...
Floyd();
EvaRk();
EvaDiaCen(); // 求直径以及绝对中心
EvaMdst(); // 求最小直径生成树
}