The K-th Distance
Time Limit: 8000/4000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 751 Accepted Submission(s): 215
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) ). In following there are n-1 lines. Each line has two integer u , v. indicate that there is an edge between node u and v.
For each case, the first line contain two integer n and K ( 2≤n≤100000,0≤K≤min(n(n−1)/2,106) ). In following there are n-1 lines. Each line has two integer u , v. indicate that there is an edge between node u and v.
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-2-3 前三小分别是1-2(1) 2-3(1) 1-2-3(2)
思路:队友把这种搜索方式称之为洪水式搜索...
就是枚举所有点,然后以当前点为点对里的第一个点在树上搜索下一个点(i,x),也就是已知i搜索x,遍历一次树,找到第k小的
这样做是对的?! NO! 是错的。 我们要的是从小到大的第k个,那么如果我们一个一个点去枚举无法保证是第k小。(以1为点对的第一个点有可能搜索长度为9,10的,这些不应该在前k小个数里)
所有我们要一次性把所有点都放到一个队列里面,然后用BFS去搜索,这样按照步数我们就能先遍历完长度为1的所有边,然后才会去遍历长度为2的边,注意“”要记录当前点是怎么来的,不能怎么来怎么去,会进入死循环。(比如从1-2,下一次你遍历2又遍历了2-1,那就死循环了)“”
因为点对会进入两次(比如1-2,2-1),所有我们要搜索前2*k个的和,然后最后除以2即可。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
using namespace std;
#define N 100010
struct Edge
{
int v,next;
} edge[N*4];
struct Node
{
int u,v,d;
} p[N*20];
int cnt,head[N];
long long ans;
int k;
queue<Node>q;
void init()
{
cnt=0;
memset(head,-1,sizeof(head));
while(!q.empty()) q.pop();
}
void addedge(int u,int v)
{
edge[cnt].v=v;
edge[cnt].next=head[u];
head[u]=cnt++;
}
void bfs()
{
int cnt=0;
while(!q.empty())
{
Node now=q.front();
q.pop();
int u=now.u,v=now.v,d=now.d;
for(int i=head[u]; i!=-1; i=edge[i].next)
{
int vv=edge[i].v;
if(vv!=v)
{
ans+=d;
cnt++;
Node next;
next.u=vv,next.v=u,next.d=d+1;
q.push(next);
}
if(cnt>=k) break;
}
if(cnt>=k) break;
}
}
int main()
{
int T,s,t;
int n;
scanf("%d",&T);
while(T--)
{
init();
scanf("%d %d",&n,&k);
Node now;
for(int i=1; i<=n; i++)
{
now.u=i,now.v=i,now.d=1;
q.push(now);
}
for(int i=1; i<n; i++)
{
scanf("%d %d",&s,&t);
addedge(s,t);
addedge(t,s);
}
ans=0;
k=k*2;
bfs();
printf("%lld\n",ans/2);
}
return 0;
}