@ZCDHJ
2019-08-14T06:50:06.000000Z
字数 3494
阅读 593
未分类
将最短路树建出来,点分治就行了。
因为最大值不能直接容斥,所以每次分别计算子树的贡献。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <cstring>
const int MAXN = 3e4;
const int MAXM = 6e4;
int n, m, K, edge1, edge2, allSize, root, ans1, ans2;
int fst1[MAXN | 1], fst2[MAXN | 1];
int f[MAXN | 1], size[MAXN | 1];
int maxx[MAXN | 1], sumx[MAXN | 1];
bool vis[MAXN | 1];
struct E {
int u, v, w;
E() : u(0), v(0), w(0) {}
E(int x, int y, int z) : u(x), v(y), w(z) {}
} a[MAXM | 1];
inline bool comp1(const E &lhs, const E &rhs) {
return lhs.v > rhs.v;
}
inline bool comp2(const E &lhs, const E &rhs) {
return lhs.u > rhs.u;
}
struct Edge {
int to, w, nxt;
Edge() : to(0), w(0), nxt(0) {}
Edge(int a, int b, int c) : to(b), w(c), nxt(a) {}
} e1[MAXM << 1 | 1], e2[MAXM << 1 | 1];
struct Heap {
int x, dis;
Heap() : x(0), dis(0) {}
Heap(int a, int b) : x(a), dis(b) {}
friend bool operator< (const Heap &lhs, const Heap &rhs) {
return lhs.dis > rhs.dis;
}
};
inline int read() {
register int x = 0;
register char ch = getchar();
while (!isdigit(ch)) ch = getchar();
while (isdigit(ch)) {
x = x * 10 + ch - '0';
ch = getchar();
}
return x;
}
void Dijkstra() {
std::priority_queue < Heap > q;
int dist[MAXN | 1];
memset(dist, 0x3f, sizeof(dist));
dist[1] = 0;
q.push(Heap(1, 0));
do {
Heap from = q.top();
q.pop();
if (from.dis != dist[from.x]) continue;
for (int k = fst1[from.x]; k; k = e1[k].nxt) {
int to = e1[k].to, w = e1[k].w;
if (dist[to] > dist[from.x] + w) {
dist[to] = dist[from.x] + w;
q.push(Heap(to, dist[to]));
}
}
} while (!q.empty());
std::queue < int > qq;
qq.push(1);
do {
int from = qq.front();
qq.pop();
for (int k = fst1[from]; k; k = e1[k].nxt) {
int to = e1[k].to, w = e1[k].w;
if (dist[to] == dist[from] + w && !vis[to]) {
vis[to] = 1;
e2[++edge2] = Edge(fst2[from], to, w);
fst2[from] = edge2;
e2[++edge2] = Edge(fst2[to], from, w);
fst2[to] = edge2;
qq.push(to);
}
}
} while (!qq.empty());
}
void getRoot(int x, int fa) {
size[x] = 1;
f[x] = 0;
for (int k = fst2[x]; k; k = e2[k].nxt) {
int to = e2[k].to;
if (to == fa || vis[to]) continue;
getRoot(to, x);
size[x] += size[to];
f[x] = std::max(f[x], size[to]);
}
f[x] = std::max(f[x], allSize - size[x]);
if (f[x] < f[root] || root == 0) root = x;
}
void getSonAns(int x, int fa, int ww, int depth) {
if (depth >= K) return;
if (maxx[K - 1 - depth] + ww > ans1) {
ans1 = maxx[K - 1 - depth] + ww;
ans2 = sumx[K - 1 - depth];
} else if (maxx[K - 1 - depth] + ww == ans1) ans2 += sumx[K - 1 - depth];
for (int k = fst2[x]; k; k = e2[k].nxt) {
int to = e2[k].to, w = e2[k].w;
if (to == fa || vis[to]) continue;
getSonAns(to, x, ww + w, depth + 1);
}
}
void getDis(int x, int fa, int ww, int depth) {
if (depth >= K) return;
if (ww > maxx[depth]) {
maxx[depth] = ww;
sumx[depth] = 1;
} else if (ww == maxx[depth]) ++sumx[depth];
for (int k = fst2[x]; k; k = e2[k].nxt) {
int to = e2[k].to, w = e2[k].w;
if (to == fa || vis[to]) continue;
getDis(to, x, ww + w, depth + 1);
}
}
void remove(int x, int fa, int ww, int depth) {
if (depth >= K) return;
maxx[depth] = 0;
sumx[depth] = 0;
for (int k = fst2[x]; k; k = e2[k].nxt) {
int to = e2[k].to, w = e2[k].w;
if (to == fa || vis[to]) continue;
remove(to, x, ww + w, depth + 1);
}
}
void getAns(int x) {
maxx[0] = 0;
sumx[0] = 1;
for (int k = fst2[x]; k; k = e2[k].nxt) {
int to = e2[k].to, w = e2[k].w;
if (!vis[to]) {
getSonAns(to, x, w, 1);
getDis(to, x, w, 1);
}
}
for (int k = fst2[x]; k; k = e2[k].nxt) {
int to = e2[k].to, w = e2[k].w;
if (!vis[to]) remove(to, x, w, 1);
}
}
void DAC(int x) {
vis[x] = 1;
getAns(x);
// printf("ffffrom=%d ans1=%d ans2=%d\n", x, ans1, ans2);
int lstSize = allSize;
for (int k = fst2[x]; k; k = e2[k].nxt) {
int to = e2[k].to;
if (vis[to]) continue;
allSize = size[to] > size[x] ? lstSize - size[x] : size[to];
root = 0;
getRoot(to, x);
DAC(root);
}
}
int main() {
n = read();
m = read();
K = read();
for (int i = 1; i <= m; ++i) {
a[i].u = read();
a[i].v = read();
a[i].w = read();
}
std::sort(a + 1, a + m + 1, comp1);
for (int i = 1; i <= m; ++i) {
e1[++edge1] = Edge(fst1[a[i].u], a[i].v, a[i].w);
fst1[a[i].u] = edge1;
}
std::sort(a + 1, a + m + 1, comp2);
for (int i = 1; i <= m; ++i) {
e1[++edge1] = Edge(fst1[a[i].v], a[i].u, a[i].w);
fst1[a[i].v] = edge1;
}
Dijkstra();
allSize = n;
memset(vis, 0, sizeof(vis));
getRoot(1, 0);
DAC(root);
printf("%d %d\n", ans1, ans2);
return 0;
}