首先最短的路径一定是各条边,然后是两条边组成的路径,所以我们可以利用宽搜的思想,利用队列每次取一条边,然后对它进行拓展,直到选够边数为止,用一个变量求和即可.
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <queue>
#define MAX 100007
using namespace std;
int t,n,k,u,v;
struct Edge
{
int v,next;
}e[MAX<<1];
struct Path
{
int u,v,l,pre;
Path ( int a , int b , int c , int d )
: u(a),v(b),l(c),pre(d)
{}
};
typedef long long LL;
int head[MAX];
int cc = 0;
void add ( int u , int v )
{
e[cc].v =v;
e[cc].next = head[u];
head[u] = cc++;
}
int main ( )
{
scanf ( "%d" , &t );
while ( t-- )
{
queue<Path> q;
LL ans = 0;
cc = 0;
memset ( head , -1 , sizeof ( head ) );
scanf ( "%d%d" , &n , &k );
for ( int i = 1 ; i < n ; i++ )
{
scanf ( "%d%d" , &u , &v );
add ( u , v );
add ( v , u );
q.push ( Path ( u , v , 1 , u) );
q.push ( Path ( v , u , 1 , v ) );
}
int cnt = 0 ;
while ( cnt < k*2 )
{
int x = q.front().u , y = q.front().v;
int l = q.front().l , pre = q.front().pre;
ans += l;
// cout << cnt << " : " << l << endl;
cnt++;
if ( cnt >= k*2 ) break;
q.pop();
if ( q.size() + cnt > k*2 ) continue;
for ( int i = head[y] ; i != -1 ; i = e[i].next )
{
int v = e[i].v;
if ( v == pre ) continue;
q.push ( Path ( x , v , l+1 , y ) );
}
}
printf ( "%I64d\n" , ans/2 );
}
}