zoukankan      html  css  js  c++  java
  • hdu 5102 The K-th Distance (队列+生成法,,)

    题意:

    N个点的一棵树。定义点u和点v的距离等于它们之间的路径(唯一的)的长度。这样我们可以得到n*(n-1)/2个距离。

    将它们从小到大排序,问前K个数的和是多少。

    思路:

    将边长为1的树枝都入队列。每次取出一个,然后从这根树枝的前端生出一个新点,变成距离加1的一根新树枝,将其入队列。如此操作下去。

    可得到所有的各种长度的树枝。因为每根树枝其实有两个在队列里(互为反方向生长),故求前2*K个数的和,然后除以2。

    *:我们取前队列里的前2K个,就算后面的若干些不是一对一对的,也一定可以取2K个以后的一些数与这2K个数的一些交换,将2K个数调整为一对一对的形式。(画个样例想想就明白了)

    例子:

    1-2-3          树枝: (1->2),(2->1),(2->3),(3->2),(1->2->3),(3->2->1)

    代码:(*:生成够2K个数就可以及时退出了,不然TLE)

    struct node{
        int u,v,len;
    }edge[2000100];
    
    vector<int> graph[100100];
    
    int T,n,k;
    
    int main(){
        cin>>T;
        while(T--){
            scanf("%d%d",&n,&k);
            int c=0;
            rep(i,1,n) graph[i].clear();
            rep(i,1,n-1){
                int x,y;
                scanf("%d%d",&x,&y);
                graph[x].push_back(y);
                graph[y].push_back(x);
                edge[++c].u=x, edge[c].v=y, edge[c].len=1;
                edge[++c].v=x, edge[c].u=y, edge[c].len=1;
            }
            int p=0;
            while(p<=c){
                if(c>=2*k) break;
                ++p;
                int U=edge[p].u, V=edge[p].v;
                int L=graph[U].size();
                rep(i,0,L-1) if(graph[U][i]!=V && c<2*k){
                    ++c;
                    edge[c].u=graph[U][i];
                    edge[c].v=U;
                    edge[c].len=edge[p].len+1;
                }
            }
            ll ans=0;
            int ts=min(c,2*k);
            rep(i,1,ts) ans+=(ll)edge[i].len;
            printf("%I64d
    ",ans/2);
        }
    }
  • 相关阅读:
    UVA 10618 Tango Tango Insurrection
    UVA 10118 Free Candies
    HDU 1024 Max Sum Plus Plus
    POJ 1984 Navigation Nightmare
    CODEVS 3546 矩阵链乘法
    UVA 1625 Color Length
    UVA 1347 Tour
    UVA 437 The Tower of Babylon
    UVA 1622 Robot
    UVA127-"Accordian" Patience(模拟)
  • 原文地址:https://www.cnblogs.com/fish7/p/4085116.html
Copyright © 2011-2022 走看看