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;
    }
  • 相关阅读:
    一百三十二:CMS系统之前端动态获取后台添加的轮播图
    一百三十一:CMS系统之轮播图上传图片功能
    一百三十:CMS系统之七牛js和python的SDK使用示例
    Python中文件编码的检测
    三目运算符
    三级菜单
    购物车程序
    计算机进制转换
    Python字典练习题
    VS Code常用快捷键总结
  • 原文地址:https://www.cnblogs.com/liyinggang/p/5660787.html
Copyright © 2011-2022 走看看