zoukankan      html  css  js  c++  java
  • 旅行

    description

    给定一颗(n)节点的边带权的无根树,求树上任意经过边数为奇数的两点间距离第(k)小.树上两点间的路径(zeta{(u,v)})的距离定义为:从(u)出发,所经过的第奇数条边权乘(1),第偶数条边边权乘上(-1),然后将这些值相加所得结果.

    solution

    这题有个非常神奇的解法.首先我们选定(1)号节点为根,然后预处理出树上所有点到根的距离(dis),不难发现,所有深度为奇数的点和所有深度为偶数的点相互组合成树上经过边数为奇数的点对集,并且奇数边数路径(xi{(u,v)})的距离可以表示为(dis[u]+dis[v]),于是我们可以把奇数深度节点的(dis)和偶数深度节点的(dis)单独拿出作为两个集合,接下来的任务即求出两集合间取两数相加所得结果的第(k)小.

    这里我们用到贪心思想,首先将数组(a)(b)排好序,然后将所有的(a_{i})(b_{1})相加,将其结果压入小根堆内,每次弹出并将(a_{i})(b_{j+1})压入,第(k)次弹出的值即为答案.

    code

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<queue>
    #define R register
    #define next MabLcdG
    #define mod 1
    #define Mod(x) ((x%mod+mod)%mod)
    using namespace std;
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    inline ll read();
    inline void write(ll x);
    inline void writesp(ll x);
    inline void writeln(ll x);
    const ll maxn=1100000;
    ll n,k; 
    ll head[maxn],next[maxn],to[maxn],tot,w[maxn];
    ll dis[maxn];
    ll h[2],res[2][maxn];
    
    inline void add(ll x,ll y,ll z){to[++tot]=y;next[tot]=head[x];head[x]=tot;w[tot]=z;}
    
    inline void dfs1(ll x,ll fa,ll deep){	
    	res[(deep&1)][(++h[(deep&1)])]=dis[x];
    	for(R ll i=head[x],ver;i;i=next[i]){
    		ver=to[i];
    		if(ver==fa) continue;
    		dis[ver]=w[i]-dis[x];
    		dfs1(ver,x,deep+1);
    	}
    }
    priority_queue<pair<ll,ll> >q;
    ll ans;
    int main(){
    	freopen("travel.in","r",stdin);
    	freopen("travel.out","w",stdout);
    	n=read();k=read();
    	for(R ll i=1,x,y,z;i<n;i++){
    		x=read();y=read();z=read();
    		add(x,y,z);add(y,x,z);
    	}
    	dfs1(1,-1,1);
    	sort(res[0]+1,res[0]+h[0]+1);
    	sort(res[1]+1,res[1]+h[1]+1);
    	if(h[0]*h[1]<k){puts("Stupid Mike");return 0;}
    	for(R ll i=1;i<=h[0];i++) q.push(make_pair(-(res[0][i]+res[1][1]),1));
    	for(R ll i=1;i<k;i++){
    		pair<ll,ll>rem=q.top();q.pop();
    		if(rem.second<h[1]) q.push(make_pair(rem.first+res[1][rem.second]-res[1][rem.second+1],rem.second+1));
    	}
    	writeln(-q.top().first);
    }
    inline ll read(){ll x=0,t=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-') t=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*t;}
    inline void write(ll x){if(x<0){putchar('-');x=-x;}if(x<=9){putchar(x+'0');return;}write(x/10);putchar(x%10+'0');}
    inline void writesp(ll x){write(x);putchar(' ');}
    inline void writeln(ll x){write(x);putchar('
    ');}
    
  • 相关阅读:
    移动布局之弹性布局
    .dpg和.webp的图片格式
    跳转不到对应的JSP页面
    CentOS7配置vsftpd3.0.2
    Linux如何将用户从一个组中移除?
    数组和方法
    运算符
    数据类型转换
    Apache的虚拟主机配置及伪静态操作
    Linux--文件的上传和下载
  • 原文地址:https://www.cnblogs.com/ylwtsq/p/13441168.html
Copyright © 2011-2022 走看看