首先最短的路径一定是各条边,然后是两条边组成的路径,所以我们可以利用宽搜的思想,利用队列每次取一条边,然后对它进行拓展,直到选够边数为止,用一个变量求和即可.
#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 ); } }