hdu 5102(巧妙的搜索)
The K-th Distance
Time Limit: 8000/4000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 752 Accepted Submission(s): 216
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 ). 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 ). 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
Source
题意:求出一棵树里面每两个点之间距离的前K大之和。
题解:
把所有边 (u,v) 以及(v,u)放入一个队列,队列每弹出一个元素(u,v),对于所有与u相邻的点w,如果w!=v,就把(w,u)入队。这样就能一个一个生成前K小的 距离。 注意到每条边实际上会入队两次,只要把K翻倍且把ans除2即可,时间复杂度为O(n+K);
这种搜索方式还是第一次看到。。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include <queue> using namespace std; const int N = 100005; int n,k,ans; struct node{ int u,v,w; node(){}; node(int _u,int _v,int _w):u(_u),v(_v),w(_w){}; }; queue<node> q; struct Edge{ int v,next; }edge[2*N]; int head[N]; int tot; void addedge(int u,int v,int &k){ edge[k].v = v,edge[k].next = head[u],head[u] = k++; } void init(){ memset(head,-1,sizeof(head)); tot= 0; } void bfs(){ int cnt = 0; while(!q.empty()){ node temp = q.front(); q.pop(); int u = temp.u,v=temp.v,w = temp.w; if(cnt>=k) break; for(int i=head[u];i!=-1;i=edge[i].next){ int _v = edge[i].v; if(_v!=v){ ans +=w+1; cnt++; q.push(node(_v,u,w+1)); } if(cnt>=k) break; } if(cnt>=k) break; } } int main(){ int tcase; scanf("%d",&tcase); while(tcase--){ while(!q.empty()) q.pop(); init(); scanf("%d%d",&n,&k); for(int i=1;i<=n;i++) q.push(node(i,0,0)); for(int i=1;i<n;i++){ int u,v; scanf("%d%d",&u,&v); addedge(u,v,tot); addedge(v,u,tot); } ans = 0; k = 2*k; bfs(); printf("%d\n",ans/2); } return 0; }