hdu 5102 The K-th Distance(特殊的搜索技巧)

来源:互联网 发布:mac 删除程序 编辑:程序博客网 时间:2024/05/22 15:01

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 (2n100000,0Kmin(n(n1)/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
23 31 22 35 71 21 32 42 5
 

Sample Output
410
题意:给一棵树,树上一条边是1,求树上所有点对里面第k小的点对对应的长度

比如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 100010struct 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;}




0 0
原创粉丝点击