The K-th Distance
Time Limit: 8000/4000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Problem Description
Given a tree, which has n node in total. Define the distance between two node u and v is the number of edge on their unique route. So we can have n(n-1)/2 numbers for all the distance, then sort the numbers in ascending order. The task is to output the sum of the first K numbers.
Input
There are several cases, first is the number of cases T. (There are most twenty cases).
For each case, the first line contain two integer n and K (
2≤n≤100000,0≤K≤min(n(n−1)/2,106)
Output
For each case output the answer.
Sample Input
2 3 3 1 2 2 3 5 7 1 2 1 3 2 4 2 5
Sample Output
4 10
用一个队列维护即可,先将所有边入队,然后不停的用边的一个端点向外扩张,每扩张一次,路径长度就+1
由于1->2和2->1会重复算,所以K要扩大一倍,那么最后的结果肯定会多算一倍,除以2即可。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
#define N 100007
struct node
{
int u,v,d;
node(int _u,int _v,int _d):u(_u),v(_v),d(_d){}
node(){}
};
struct Edge{
int v,next;
}G[2*N];
int ans,k,tot,head[N];
queue<node> q;
void addedge(int u,int v)
{
G[tot].v = v;
G[tot].next = head[u];
head[u] = tot++;
}
void bfs()
{
int cnt = 0;
while(!q.empty())
{
node tmp = q.front();
q.pop();
int u = tmp.u, v = tmp.v, d = tmp.d;
if(cnt >= k) break;
for(int i = head[u]; i != -1; i = G[i].next)
{
int vv = G[i].v;
if(vv != v)
{
ans += d+1;
cnt++;
q.push(node(vv,u,d+1));
}
if(cnt >= k) break;
}
}
}
int main()
{
int t,n,u,v,i;
scanf("%d",&t);
while(t--)
{
while(!q.empty()) q.pop();
scanf("%d%d",&n,&k);
tot = 0;
memset(head,-1,sizeof(head));
for(i = 1; i <= n; i++) q.push(node(i,i,0));
for(i = 1; i < n; i++)
{
scanf("%d%d",&u,&v);
addedge(u,v);
addedge(v,u);
}
k *= 2;
ans = 0;
bfs();
cout<<ans/2<<endl;
}
return 0;
}