HDU 5102 The K-th Distance(模拟)

题意:输入一棵树,输出前k小的点对最短距离dis(i,j)的和。

 

模拟,官方题解说得很清楚了。不重复了。

http://bestcoder.hdu.edu.cn/

 

需要注意的是,复杂度要O(n+k),不能用set,map之类的标记是否访问。

一开始TLE了,去掉标记后wa了。最后发现对队列的元素加个前缀,就可以了,即标记该条边是从哪个点延伸的。

 

#include <cstdio>
#include <cstring>
#include <iostream>
#include <cmath>
#include <algorithm>
#include <vector>
#include <string>
#include <set>
#include <queue>
#include <map>
using namespace std;

#define ll long long
#define MP make_pair

#define inf 1e9
#define eps 1e-8

#define maxn 110000
#define maxm 210000
int que[2100000][4];
struct Edge{
    int v,nxt;
}e[maxm];
int head[maxn],esz;
void init(){esz=0;memset(head,-1,sizeof(head));}
void addedge(int u,int v){
    e[esz].v=v,e[esz].nxt=head[u];
    head[u]=esz++;
}
int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        int n,m;
        scanf("%d%d",&n,&m);
        m<<=1;
        int sz=0;
        init();
        for(int i=1;i<n;++i){
            int u,v;
            scanf("%d%d",&u,&v);
            addedge(u,v);
            addedge(v,u);
            if(sz<m){
                que[sz][0]=u,que[sz][1]=v,que[sz][2]=1;
                que[sz][3]=-1;
                ++sz;
            }
            if(sz<m){
                que[sz][0]=v,que[sz][1]=u,que[sz][2]=1;
                que[sz][3]=-1;
                ++sz;
            }
        }
        int H=0,T=sz;
        ll ans=0;
        for(int i=0;i<m;++i){
            int dis = que[H][2];
            int u = que[H][0], v = que[H][1];
            int pre = que[H][3];
            ++H;
            for(int j=head[u];j!=-1 && T<m;j=e[j].nxt){
                int uu = e[j].v;
                if(uu==v || uu==pre) continue;
                que[T][0]=uu,que[T][1]=v,que[T][2]=dis+1;
                que[T][3]=u;
                T++;
            }
            ans+=dis;
        }
        printf("%I64d\n",ans>>1);
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/nextbin/p/4085656.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值