zoukankan      html  css  js  c++  java
  • 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 (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
    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
    ",ans/2);
        }
        return 0;
    }
  • 相关阅读:
    Linux Core Dump
    ODP.NET Managed正式推出
    获取EditText的光标位置
    (Java实现) 洛谷 P1603 斯诺登的密码
    (Java实现) 洛谷 P1603 斯诺登的密码
    (Java实现) 洛谷 P1036 选数
    (Java实现) 洛谷 P1036 选数
    (Java实现) 洛谷 P1012 拼数
    (Java实现) 洛谷 P1012 拼数
    (Java实现) 洛谷 P1028 数的计算
  • 原文地址:https://www.cnblogs.com/liyinggang/p/5660787.html
Copyright © 2011-2022 走看看