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;
    }
  • 相关阅读:
    MKMapVIew学习系列2 在地图上绘制出你运行的轨迹
    WPF SDK研究 Intro(6) WordGame1
    WPF SDK研究 Intro(3) QuickStart3
    WPF SDK研究 Layout(1) Grid
    WPF SDK研究 目录 前言
    WPF SDK研究 Intro(7) WordGame2
    WPF SDK研究 Layout(2) GridComplex
    对vs2005创建的WPF模板分析
    WPF SDK研究 Intro(4) QuickStart4
    《Programming WPF》翻译 第6章 资源
  • 原文地址:https://www.cnblogs.com/liyinggang/p/5660787.html
Copyright © 2011-2022 走看看