zoukankan      html  css  js  c++  java
  • LCA【bzoj3364】: [Usaco2004 Feb]Distance Queries 距离咨询

    【bzoj3364】: [Usaco2004 Feb]Distance Queries 距离咨询

    Description

    ​ 奶牛们拒绝跑马拉松,因为她们悠闲的生活无法承受约翰选择的如此长的赛道.因此约翰决心找一条更合理的赛道,他打算咨询你.此题的地图形式与前两题相同.但读入地图之后,会有K个问题.每个问题包括2个整数,就是约翰感兴趣的2个农场的编号,请尽快算出这2个农场间的距离.

    Input

    ​ 第1到I+M行:与前两题相同;

    ​ 第2+M行:一个整数K(1≤K≤10000).

    ​ 第3+M到2+M+K行:每行输入2个整数,代表两个农场.

    Output

    ​ 对每个问题,输出单独的一个整数,给出正确的距离.

    倍增模板题。

    注意long long RE了好几次。

    code:

    #include<iostream>
    #include<cstdio>
    #define int long long
    using namespace std;
    const int wx=40017;
    inline int read(){
    	int sum=0,f=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){sum=(sum<<1)+(sum<<3)+ch-'0';ch=getchar();}
    	return sum*f;
    }
    int n,m,num;
    int head[wx],dep[wx],f[wx][18],dis[wx][18];
    struct e{
    	int nxt,to,dis;
    }edge[wx*2];
    void add(int from,int to,int dis){
    	edge[++num].nxt=head[from];
    	edge[num].to=to;
    	edge[num].dis=dis;
    	head[from]=num;
    }
    void dfs(int u,int fa){
    	dep[u]=dep[fa]+1;
    	for(int i=head[u];i;i=edge[i].nxt){
    		int v=edge[i].to;
    		if(v==fa)continue;
    		f[v][0]=u;dis[v][0]=edge[i].dis;
    		dfs(v,u);
    	}
    }
    void pre(){
    	for(int j=1;j<=17;j++){
    		for(int i=1;i<=n;i++){
    			f[i][j]=f[f[i][j-1]][j-1];
    			dis[i][j]=dis[i][j-1]+dis[f[i][j-1]][j-1];
    		}
    	}
    }
    int LCA(int x,int y){
    	int re=0;
    	if(dep[x]<dep[y])swap(x,y);
    	for(int i=17;i>=0;i--){
    		if(dep[f[x][i]]>=dep[y]){
    			re+=dis[x][i];x=f[x][i];
    		}
    	}
    	if(x==y)return re;
    	for(int i=17;i>=0;i--){
    		if(f[x][i]!=f[y][i]){
    			re+=dis[x][i];re+=dis[y][i];
    			x=f[x][i],y=f[y][i];
    		}
    	}
    	return re+dis[x][0]+dis[y][0];
    }
    signed main(){
    	n=read();read();
    	for(int i=1;i<n;i++){
    		int x,y,z;
    		x=read();y=read();z=read();scanf("%s");
    		add(x,y,z);add(y,x,z);
    	}
    	dfs(1,0);pre();
    	m=read();
    	for(int i=1;i<=m;i++){
    		int x,y;
    		x=read();y=read();
    		printf("%d
    ",LCA(x,y));
    	}
    	return 0;
    }
    
  • 相关阅读:
    nyoj999 师傅又被妖怪抓走了 (预处理+bfs+状态压缩)
    使用逆波兰式进行表达式求值
    [moses笔记]编译含有nplm的moses解码器
    菲波那契数列编程实现
    引领网页设计潮流的优秀网页作品赏析
    MFC中获取各个窗口之间的句柄或者指针对象的方法
    UVALive 6529 Eleven 区间dp
    jquery 实现菜单的下拉菜单
    数字图像和视频处理的基础-第4周运动预计matlab练习题
    setjmp与longjmp
  • 原文地址:https://www.cnblogs.com/wangxiaodai/p/9766523.html
Copyright © 2011-2022 走看看