自己写的第一个树分治,mark一下~~
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<queue>
#include<cmath>
#include<stack>
#include<set>
#include<map>
#define INF 0x3f3f3f3f
#define lowbit(x) (x&(-x))
#define LLINF 0x3f3f3f3f3f3f3f3fll
#define CLR(a, b) memset(a, b, sizeof(a))
using namespace std;
#ifdef __int64
typedef __int64 LL;
#else
typedef long long LL;
#endif
const int maxn = 100100;
struct Edge
{
int u, v, c;
Edge(){}
Edge(int u, int v, int c)
:u(u), v(v), c(c){}
}E[maxn*2];
vector<pair<int, int> > G[maxn];
int fir[maxn], nxt[maxn*4], tot = 0;
int d[maxn];
bool vis[maxn];
void Add_Edge(int u, int v, int c)
{
E[tot] = Edge(u, v, c);
nxt[tot] = fir[u]; fir[u] = tot ++;
}
void init(int n)
{
tot = 0; CLR(fir, -1);
for(int i = 1; i <= n; i ++) G[i].clear();
}
int n, m, k;
int ans1, ans2;
void spfa(int s)
{
CLR(d, INF);
CLR(vis, false);
d[s] = 0;
queue<int> q;
q.push(s);
while(!q.empty())
{
int u = q.front();q.pop();
vis[u] = false;
for(int i = 0; i < G[u].size(); i ++)
{
pair<int, int> p = G[u][i];
int v = p.first, c = p.second;
if(d[v] > d[u] + c)
{
d[v] = d[u] + c;
if(!vis[v]) q.push(v), vis[v] = true;
}
}
}
}
void dfs(int u)
{
vis[u] = true;
sort(G[u].begin(), G[u].end());
for(int i = 0; i < G[u].size(); i ++)
{
pair<int, int> p = G[u][i];
int v = p.first, c = p.second;
if(vis[v]) continue;
if(d[v] == d[u] + c)
{
Add_Edge(u, v, c);
Add_Edge(v, u, c);
dfs(v);
}
}
}
int cnt[maxn], root, minc, siz;
int md[maxn], tm[maxn], cc[maxn], tc[maxn], nw[maxn];
int tree_sz(int u, int fa)
{
if(vis[u]) return 0;
int ret = 1;
for(int i = fir[u]; ~i; i = nxt[i])
{
Edge e = E[i];
if(e.v == fa) continue;
ret += tree_sz(e.v, u);
}
return ret;
}
void tree_root(int u, int fa)
{
int mx = 0, mn = siz - 1; cnt[u] = 1;
for(int i = fir[u]; ~i; i = nxt[i])
{
Edge e = E[i];
if(e.v == fa) continue;
if(vis[e.v]) continue;
tree_root(e.v, u);
mx = max(mx, cnt[e.v]); mn = min(mn, cnt[e.v]);
cnt[u] += cnt[e.v];
}
if(mn <= mx) mx = max(mx, siz - cnt[u]), mn = min(mn, siz - cnt[u]);
else swap(mn, mx);
if(mx - mn < minc) minc = mx - mn, root = u;
}
void tree_calc(int u, int fa, int lvl)
{
for(int i = fir[u]; ~i; i = nxt[i])
{
Edge e = E[i];
if(e.v == fa || vis[e.v]) continue;
if(lvl == 0) for(int j = 1; tc[j]; j ++)
{
tm[j] = -1; tc[j] = 0;
}
nw[lvl + 1] = nw[lvl] + e.c;
tree_calc(e.v, u, lvl + 1);
if(lvl == 0) for(int j = 1; tc[j]; j ++)
{
if(cc[k - j - 1] && ans1 < tm[j] + md[k - j - 1])
{
ans1 = tm[j] + md[k - j - 1];
ans2 = cc[k - j - 1] * tc[j];
}
else if(cc[k - j - 1] && ans1 == tm[j] + md[k - j - 1])
ans2 += cc[k - j - 1] * tc[j];
}
if(lvl == 0) for(int j = 1; tc[j]; j ++)
{
if(tm[j] > md[j]) md[j] = tm[j], cc[j] = tc[j];
else if(tm[j] == md[j]) cc[j] += tc[j];
}
}
if(!lvl) return ;
if(nw[lvl] > tm[lvl]) tm[lvl] = nw[lvl], tc[lvl] = 1;
else if(nw[lvl] == tm[lvl]) tc[lvl] ++;
}
void tree_div(int u)
{
siz = tree_sz(u, -1);
if(siz < k) return ;
minc = INF; tree_root(u, -1);
CLR(md, -1); CLR(cc, 0);
u = root; nw[0] = 0;
md[0] = 0; cc[0] = 1;
tree_calc(u, -1, 0);
vis[u] = true;
for(int i = fir[u]; ~i; i = nxt[i])
{
Edge e = E[i];
if(vis[e.v]) continue;
tree_div(e.v);
}
}
void solve()
{
init(n);
for(int i = 0; i < m; i ++)
{
int u, v, c;
scanf("%d%d%d", &u, &v, &c);
G[u].push_back(make_pair(v, c));
G[v].push_back(make_pair(u, c));
}
spfa(1);
CLR(vis, false);
dfs(1);
ans1 = ans2 = 0;
CLR(vis, false);
tree_div(1);
printf("%d %d\n", ans1, ans2);
}
int main()
{
// freopen("1011.in", "r", stdin);
// freopen("1011.txt", "w", stdout);
int T, cas = 1;
scanf("%d", &T);
while(T --)
{
scanf("%d%d%d", &n, &m, &k);
solve();
}
}