【树链+EXGCD】杭电多校第一场 A

news2025/2/27 4:35:19

1001 Hide-And-Seek Game (hdu.edu.cn)

题意:

给定一棵树和两条路径,每条路径都有起点和终点,起始时起点有人,每隔一秒都会往终点走一步,会从起点走向终点再会起点这样不断地周期性地走,让你求一点,使得两个人能在这点相遇且花的时间最少

 

思路:

首先答案一定是两条路径相交的点中的一个,因此可以把一条路径标记一下,然后对于另一条路径去check是否重合

对于树链的操作,只需要求出LCA,分成两部分,暴力跳即可

找出重合的点,即可能是答案的点之后,需要处理怎么样才能使时间最少

比赛的时候只是分成四种情况讨论,并没有解方程,赛后调了很久也没有全对,但是只是几个数据没过,也根本调不出来

那就这样吧,反正大部分都对了 (

Code:

#include <bits/stdc++.h>

#define int long long

using namespace std;

const int mxn=3e3+10;
const int mxe=3e3+10;
const int Inf=1e18;

struct ty{
	int to,next;
}edge[mxe<<2];

int N,M,Q,u,v,s1,t1,s2,t2,k1,k2;
int tot=0;
int a[mxn];
int head[mxn],dep[mxn],F[mxn][33];

void add(int u,int v){
	edge[tot].to=v;
	edge[tot].next=head[u];
	head[u]=tot++;
}
void G_init(){
	tot=0;
	for(int i=0;i<=N;i++){
		head[i]=-1;
        dep[i]=0;
        for(int j=0;j<=30;j++) F[i][j]=0;
	}
}
void dfs(int u,int fa){
    dep[u]=dep[fa]+1;
    F[u][0]=fa;
    for(int j=1;j<=30;j++) F[u][j]=F[F[u][j-1]][j-1];
    for(int i=head[u];~i;i=edge[i].next){
        if(edge[i].to==fa) continue;
        dfs(edge[i].to,u);
    }
}
int lca(int u,int v){
    if(dep[u]<dep[v]) swap(u,v);
    for(int j=30;j>=0;j--){
        if(dep[F[u][j]]>=dep[v]){
            u=F[u][j];
        }
    }
    if(u==v) return u;
    for(int j=30;j>=0;j--){
        if(F[u][j]!=F[v][j]){
            u=F[u][j];
            v=F[v][j];
        }
    }
    return F[u][0];
}
int dist(int u,int v){
    return dep[u]+dep[v]-2*dep[lca(u,v)];
}
int exgcd(int a,int b,int &k1,int &k2){
    if(!b){
        k1=1;k2=0;
        return a;
    }
    int d=exgcd(b,a%b,k2,k1);
    k2-=(a/b)*k1;
    return d;
}
void solve(){
	cin>>N>>M;
	G_init();
    for(int i=1;i<=N-1;i++){
        cin>>u>>v;
        add(u,v);
        add(v,u);
    }
    dfs(1,0);
    while(M--){
        cin>>s1>>t1>>s2>>t2;
        int G=lca(s1,t1);
        int s11=s1,t11=t1;
        if(dep[s11]<dep[t11]) swap(s11,t11);
        int cur=s11;
        map<int,int> mp;
        //链上的点
        int L1=0,L2=0;
        while(cur!=G){
            mp[cur]=1;
            L1++;
            cur=F[cur][0];
        }
        cur=t11;
        while(cur!=G){
            mp[cur]=1;
            L1++;
            cur=F[cur][0];
        }
        mp[G]=1;
        //L1++;
        int s22=s2,t22=t2;
        if(dep[s22]<dep[t22]) swap(s22,t22);
        cur=s22;
        int G2=lca(s22,t22);
        vector<int> V;
        //路径交点
        while(cur!=G2){
            L2++;
            if(mp.count(cur)) V.push_back(cur);
            cur=F[cur][0];
        }
        cur=t22;
        while(cur!=G2){
            L2++;
            if(mp.count(cur)) V.push_back(cur);
            cur=F[cur][0];
        }
        if(mp.count(G2)) V.push_back(G2);
        //L2++;
        if(V.empty()){
            cout<<-1<<'\n';
            continue;
        }
        set<pair<int,int> > ansv;
        for(auto x:V){
            //1==3
            int D1=exgcd(2*L1,-2*L2,k1,k2);
            int N2=dist(s2,x)-dist(s1,x);
            k1=k1*N2/D1;
            if(N2%D1==0){
                k1=k1*N2/D1;
                //包含0这个解,不需要%r+r
                ansv.insert({dist(s1,x)+2*k1*L1,x});
            }
            //1==4
            int D2=exgcd(2*L1,-2*L2,k1,k2);
            int N3=L2+dist(t2,x)-dist(s1,x);
            k1=k1*N3/D2;
            if(N3%D2==0){
                k1=k1*N3/D2;
                ansv.insert({dist(s1,x)+2*k1*L1,x});
            }
            //2==3
            int D3=exgcd(2*L1,-2*L2,k1,k2);
            int N4=dist(s2,x)-L1-dist(x,t1);
            k1=k1*N4/D3;
            if(N4%D3==0){
                k1=k1*N4/D3;
                ansv.insert({L1+dist(x,t1)+2*k1*L1,x});
            }
            //2==4
            int D4=exgcd(2*L1,-2*L2,k1,k2);
            int N5=L2+dist(t2,x)-L1-dist(x,t1);
            k1=k1*N5/D4;
            if(N5%D4==0){
                k1=k1*N5/D4;
                ansv.insert({L1+dist(x,t1)+2*k1*L1,x});
            }
        }
        if(ansv.empty()) cout<<-1<<'\n';
        else{
            cout<<(*ansv.begin()).second<<'\n';
        }
    }
}
signed main(){
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	int __=1;cin>>__;
	while(__--)solve();return 0;
}

 

标程:

#include<cstdio>
#include<algorithm>
#include<cmath>
#define M 5005
using namespace std;
struct E{
	int to,nx;
}edge[M<<1];
int tot,head[M];
void Addedge(int a,int b){
	edge[++tot].to=b;
	edge[tot].nx=head[a];
	head[a]=tot;
}
int sz[M],son[M],top[M],dep[M];
int Dfn[M],Low[M],tot_dfs;
int fa[M];
void dfs(int now){
	Dfn[now]=++tot_dfs;
	sz[now]=1;son[now]=0;
	for(int i=head[now];i;i=edge[i].nx){
		int nxt=edge[i].to;
		if(nxt==fa[now])continue;
		fa[nxt]=now;
		dep[nxt]=dep[now]+1;
		dfs(nxt);
		sz[now]+=sz[nxt];
		if(sz[son[now]]<sz[nxt])son[now]=nxt;
	}
	Low[now]=tot_dfs;
}
void dfs_top(int now){
	if(son[now]){
		top[son[now]]=top[now];
		dfs_top(son[now]);
	}
	for(int i=head[now];i;i=edge[i].nx){
		int nxt=edge[i].to;
		if(nxt==fa[now]||nxt==son[now])continue;
		top[nxt]=nxt;
		dfs_top(nxt);
	}
}
int LCA(int a,int b){
	while(top[a]!=top[b]){
		if(dep[top[a]]<dep[top[b]])b=fa[top[b]];
		else a=fa[top[a]];
	}
	return dep[a]<dep[b]?a:b;
}
bool In(int x,int y){
	return Dfn[y]<=Dfn[x]&&Dfn[x]<=Low[y];
}
int mark[M];
struct Point{
	int a,b;
};
Point Data[M][2];
int exgcd(int a,int b,int &x,int &y){
	int d=a; if(b==0) x=1,y=0; else{
		d=exgcd(b,a%b,y,x),y-=a/b*x;
	}
	return d;
}
int Get_ans(Point p1,Point p2){
	int val=p2.b-p1.b;
	val%=p2.a;
	while(val<0)val+=p2.a;
	while(val>p2.a)val-=p2.a;
	int a=p1.a,b=-p2.a;
	int x,y,d=exgcd(a,b,x,y);
	if(val%d!=0)return 1e9;
	x*=val/d;y*=val/d;
	int p=b/d,q=a/d;
	if(x<0){
		int k=ceil((1.0-x)/p);
		x+=p*k,y-=q*k;
	}else if(x>=0){
		int k=(x-1)/p;
		x-=p*k,y+=q*k;
	}
	return a*x+p1.b;
}
int main(){
	int T;
	scanf("%d",&T);
	while(T--){
		int n,m;
		tot=0;
		scanf("%d%d",&n,&m);
		tot_dfs=0;
		for(int i=1;i<=n;i++)head[i]=mark[i]=0;
		for(int i=1;i<n;i++){
			int a,b;
			scanf("%d%d",&a,&b);
			Addedge(a,b);
			Addedge(b,a);
		}
		dfs(1);
		top[1]=1;
		dfs_top(1);
		for(int step=1;step<=m;step++){
			int a,b,c,d;
			scanf("%d%d%d%d",&a,&b,&c,&d);
			if(a==c){printf("%d\n",a);continue;}
			int x1=LCA(a,b),x2=LCA(c,d);
			if(dep[x1]>dep[x2]){
				swap(a,c);
				swap(b,d);
				swap(x1,x2);
			}
			if(!In(a,x2)&&!In(b,x2)){
				puts("-1");
				continue;
			}
			int d1=dep[a]+dep[b]-2*dep[x1],d2=dep[c]+dep[d]-2*dep[x2];
			int p=a;
			while(1){
				Data[p][0]=(Point){2*d1,dep[a]-dep[p]};
				Data[p][1]=(Point){2*d1,2*d1-(dep[a]-dep[p])};
				mark[p]=step;
				if(p==x1)break;
				p=fa[p];
			}
			p=b;
			while(p!=x1){
				Data[p][0]=(Point){2*d1,d1-(dep[b]-dep[p])};
				Data[p][1]=(Point){2*d1,d1+(dep[b]-dep[p])};
				mark[p]=step;
				p=fa[p];
			}
			
			int ans_val=1e9,ans=-1;
			p=c;
			while(1){
				Point p1=(Point){2*d2,dep[c]-dep[p]};
				Point p2=(Point){2*d2,2*d2-(dep[c]-dep[p])};
				if(mark[p]==step){
					int res=1e9;
					res=min(min(Get_ans(p1,Data[p][0]),Get_ans(p1,Data[p][1])),min(Get_ans(p2,Data[p][0]),Get_ans(p2,Data[p][1])));
					if(res<ans_val){
						ans_val=res;
						ans=p;
					}
				}
				if(p==x2)break;
				p=fa[p];
			}
			p=d;
			while(p!=x2){
				Point p1=(Point){2*d2,d2-(dep[d]-dep[p])};
				Point p2=(Point){2*d2,d2+(dep[d]-dep[p])};
				if(mark[p]==step){
					int res=1e9;
					res=min(min(Get_ans(p1,Data[p][0]),Get_ans(p1,Data[p][1])),min(Get_ans(p2,Data[p][0]),Get_ans(p2,Data[p][1])));
					if(res<ans_val){
						ans_val=res;
						ans=p;
					}
				}
				p=fa[p];
			}
			printf("%d\n",ans);
		}
	}
	return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/767454.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

线上 OOM 频发,MyBatis 有坑...

继上次线上 CPU 出现了报警&#xff0c;这次服务又开始整活了&#xff0c;风平浪静了没几天&#xff0c;看生产日志服务的运行的时候&#xff0c;频繁的出现 OutOfMemoryError&#xff0c;就是我们俗称的 OOM&#xff0c;这可还行&#xff01; 频繁的 OOM 直接会造成服务处于一…

编程小白的自学笔记十(python爬虫入门二+实例代码详解)

系列文章目录 编程小白的自学笔记九&#xff08;python爬虫入门代码详解&#xff09; 编程小白的自学笔记八&#xff08;python中的多线程&#xff09; 编程小白的自学笔记七&#xff08;python中类的继承&#xff09; 编程小白的自学笔记六&#xff08;python中类的静态方法…

pandas 笔记:pivot_table 数据透视表

1 基本使用方法 pandas.pivot_table(data, valuesNone, indexNone, columnsNone, aggfuncmean, fill_valueNone, marginsFalse, dropnaTrue, margins_nameAll, observedFalse, sortTrue)2 主要参数 dataDataFramevalues要进行聚合的列index在数据透视表索引&#xff08;index…

flask基本用法小白教程+按钮跳转到指定页面+python和pip安装(后附)

一、flask学习教程&#xff1a; 1.1 基本程序&#xff1a; 大家可以在pycharm中复制如下代码&#xff0c;先感受一下flask的基本用法&#xff1a; 点击链接可进入浏览器查看程序运行的结果&#xff0c;在127.0.0.1:5000后面添上/test1/等设定的文字&#xff0c;可查看不同函…

Python生成exe文件运行出现黑框闪退如何查看运行bug?

cmd进行回车 第一&#xff1a;进入到可执行exe文件目录&#xff0c;如下图所示 第二&#xff1a;输入可执行文件名&#xff0c;然后就会出现报错提示

(转载)BP神经网络的非线性系统建模(matlab实现)

1案例背景 在工程应用中经常会遇到一些复杂的非线性系统,这些系统状态方程复杂,难以用数学方法准确建模。在这种情况下,可以建立BP神经网络表达这些非线性系统。方法把未知系统看成是一个黑箱,首先用系统输入输出数据训练BP神经网络,使网络能够表达该未知函数,然后用训练好的 B…

【外卖系统】环境的搭建

搭建数据库 1.创建数据库&#xff0c;名字叫reiggie 2.导入数据库 创建Maven项目 1.创建项目 2.检查项目新建的是否有问题 3.导入pom.xml文件 4.导入application.yml文件 在从gittee上down的代码的基础上&#xff0c;修改一下端口号&#xff0c;数据库的名称什么的 …

(数组与矩阵) 剑指 Offer 29. 顺时针打印矩阵 ——【Leetcode每日一题】

❓ 剑指 Offer 29. 顺时针打印矩阵 难度&#xff1a;简单 输入一个矩阵&#xff0c;按照从外向里以顺时针的顺序依次打印出每一个数字。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,2,3],[4,5,6],[7,8,9]] 输出&#xff1a;[1,2,3,6,9,8,7,4,5] 示例 2&#xff1a; 输…

DP转HDMI方案芯片-CS5218/CS5263/CS5363/CS5463详细参数对比说明

CS5218/CS5263/CS5363/CS5463都可用于设计DP转HDMI转接线方案&#xff0c;但几者间不管封装还是功能参数都有差异&#xff0c;如下介绍对比下&#xff1a; CS5218 DP to HDMI(4K30HZ) &#xff0c;CS5218管脚定义参数说明和设计电路图&#xff1a; ​ ​ CS5263 DP to HDMI 4…

Kubernetes_1.27.3_Harbor结合Nacos实战

Nacos 实战 作者:行癫(盗版必究) 一:Nacos简介 1.简介 ​ Nacos是 Dynamic Naming and Configuration Service的首字母简称,一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台;Nacos 致力于帮助您发现、配置和管理微服务;Nacos 提供了一组简单易用的特…

计讯物联5G千兆网关TG463在电力智能巡检机器人的应用功能解析

项目背景 随着国家智能电网建设加速推进&#xff0c;投资规模持续扩大&#xff0c;我国电网智能化、信息化不断提高&#xff0c;传统的电力运维与管理模式早已不能满足智能电网快速发展的需求。因此&#xff0c;在5G无线通信、人工智能、物联网、云计算、大数据、电力等前沿技术…

Error: The client is unauthorized due to authentication failure.解决办法

进入到neo4j的安装目录 修改neo4j.conf配置文件 把红框的注释#去掉保存后&#xff0c;重新运行neo4j,问题解决

【Python统计与数据分析实战_01】位置与分散程度的度量

数据描述性分析 1.描述统计量1.1 位置与分散程度的度量1.1.1 例子一 单维数组1.1.2 例子二 多维数组 1.2 关系度量1.3 分布形状的度量1.3.1 统计量&#xff1a;偏度和峰度 1.4 数据特性的总括 1.描述统计量 数据的统计分析分为统计描述和统计推断两部分。前者通过绘制统计图、…

Vue3.0的设计目标是什么?做了哪些优化?

一、设计目标 不以解决实际业务痛点的更新都是耍流氓,下面我们来列举一下Vue3之前我们或许会面临的问题 随着功能的增长,复杂组件的代码变得越来越难以维护 缺少一种比较「干净」的在多个组件之间提取和复用逻辑的机制 类型推断不够友好 bundle的时间太久了 而 Vue3 经过长达…

RuoYi-Vue/vue项目访问 webpack 中定义的变量

前言 RuoYi-Vue 3.8.4 webpack 中定义的变量 vue.config.js 中定义的 webpack 的变量 在html页面中&#xff0c;如何访问 webpack 的变量 <title><% webpackConfig.name %></title>参考&#xff1a;ruoyi-ui/public/index.html 文件

【分布式训练】基于Pytorch的分布式数据并行训练

基于Pytorch的分布式数据并行训练 动机为什么要并行分布数据&#xff1f;现有资料的不足 Outline整体框架图带解释的最小demo示例没有multiprocessing开启multiprocessing 分布式训练启动方式混合精度训练&#xff08;采用apex&#xff09; 参考资料 简介&#xff1a; 在PyTorc…

一则 MySQL 参数设置不当导致复制中断的故障案例

本文分享了一个数据库参数错误配置导致复制中断的问题&#xff0c;以及对参数配置的建议。 作者&#xff1a;秦福朗 爱可生 DBA 团队成员&#xff0c;负责项目日常问题处理及公司平台问题排查。热爱互联网&#xff0c;会摄影、懂厨艺&#xff0c;不会厨艺的 DBA 不是好司机&…

Linux学习之运算符

是赋值运算符&#xff0c;可以把一个变量设置上特定的值&#xff0c;而算术运算符就包括加减乘除&#xff08;、-、*、/&#xff09;&#xff0c;需要使用expr这个命令进行运算。 expr 5 7可以计算出来5与7的和&#xff0c;使用echo $?可以看到expr 5 7这个命令的返回值是0&…

神经网络正则化之BN/LN/GN的原理

1. BN层原理 torch.nn.BatchNorm2d(num_features, eps1e-05, momentum0.1, affineTrue, track_running_statsTrue,deviceNone,dtypeNone) 为什么用BN? 加速训练。之前训练慢是因为在训练过程中&#xff0c;整体分布逐渐往非线性函数的取值区间的上下限端靠近(参考sigmoid函数…

10.6.5 【Linux】分区命令: split

如果你有文件太大&#xff0c;导致一些携带式设备无法复制的问题&#xff0c;split可以将一个大文件&#xff0c;依据文件大小或行数来分区&#xff0c;可以将大文件分区成为小文件&#xff0c;快速有效。 将文件分区的话&#xff0c;使用-b size来将一个分区的文件限制其大小&…