CF :K 一个含n条边的带权无向连通图,q次查询,每次查询两点间的最短距离。...
题意:给你一个含n条边的带权无向连通图,q次查询,每次查询两点间的最短距离。
思路:LCA+思维。
设a,b两点间的距离为f(a,b) 则f(a,b)=dis[a]+dis[b]-2*dis[lca(a,b)];
由于n条边,因此我们先任取一条边,设这条边为X,Y,权值为Z,设查询的点为x,y,则答案为
min(f(a,b),f(a,X)+f(b,X),f(a,Y)+f(b,Y),f(a,X)+f(b,Y)+Z,f(a,Y)+f(b,X)+Z);
#include<bits/stdc++.h> #define lson (i<<1) #define rson (i<<1|1)using namespace std; typedef long long ll; const int N =1e5+5;struct node {int u,v,next;int id,f;ll w; }edge[N*2];struct node1 {int l,r;ll w;ll lz; }tr[N<<2];int tot,head[N]; int n,q; int anc[N<<1][20];int dfn; int dfns[N*2]; int dep[N*2]; int pos[N]; int inde[N]; int L[N]; int R[N]; int clo;int to[N]; int vis[N]; ll ww[N];int uu,vv; ll cost; int huan; int idd;void init() {tot=0;memset(head,-1,sizeof(head));memset(vis,0,sizeof(vis));memset(inde,-1,sizeof(inde));memset(pos,-1,sizeof(pos));clo=0; huan=0; idd=0; dfn=0; /// dfn竟然没清零 MMP }void add(int u,int v,ll w,int id) {edge[++tot].u=u; edge[tot].v=v; edge[tot].id=id; edge[tot].w=w; edge[tot].f=0;edge[tot].next=head[u]; head[u]=tot; }void dfs1(int u,int fa) {if(vis[u]){uu=fa; vv=u; huan=1; return ;}vis[u]=1;for(int i=head[u];i!=-1;i=edge[i].next){int v=edge[i].v;if(v==fa) continue;dfs1(v,u);} }void dfs2(int u,int deep) /// dfs序 {//cout<<" u "<<u<<" deep "<<deep<<endl;dfns[dfn]=u; dep[dfn]=deep; pos[u]=dfn++;L[u]=++clo;inde[u]=L[u]; /// 记录u在线段树中的位置for(int i=head[u];i!=-1;i=edge[i].next){if(edge[i].f) continue; /// 如果是标记的边跳过int v=edge[i].v;if(pos[v]==-1){to[edge[i].id]=v; /// 表示这条边指向哪个点?dfs2(v,deep+1);dfns[dfn]=u; dep[dfn++]=deep;}}R[u]=clo; }void init_RMQ(int n) /// dfn {for(int i=1;i<=n;++i) anc[i][0]=i;for(int j=1;(1<<j)<=n;++j)for(int i=1;i+(1<<j)-1<=n;++i){if(dep[anc[i][j-1]]<dep[anc[i+(1<<(j-1))][j-1]]) anc[i][j]=anc[i][j-1];else anc[i][j]=anc[i+(1<<(j-1))][j-1];} }inline int RMQ(int L,int R) {int k=0;while(1<<(k+1)<=R-L+1) ++k;if(dep[anc[L][k]]<dep[anc[R-(1<<k)+1][k]]) return anc[L][k];return anc[R-(1<<k)+1][k]; }inline int LCA(int u,int v) {if(pos[u]>pos[v]) return dfns[RMQ(pos[v],pos[u])];return dfns[RMQ(pos[u],pos[v])]; }void push_up(int i) {tr[i].w=tr[lson].w+tr[rson].w; }void push_down(int i) {if(tr[i].lz){ /// 查询只有点查询,所以不必更新区间点的sumll &lz=tr[i].lz;tr[lson].lz+=lz; tr[rson].lz+=lz;tr[lson].w+=lz; tr[rson].w+=lz;lz=0;} }void build(int i,int l,int r) {tr[i].l=l; tr[i].r=r; tr[i].w=0; tr[i].lz=0;if(l==r) return ;int mid=(l+r)>>1;build(lson,l,mid);build(rson,mid+1,r); }void update(int i,int l,int r,ll w) {if(tr[i].l==l&&tr[i].r==r){tr[i].lz+=w; tr[i].w+=w;return ;}push_down(i);int mid=(tr[i].l+tr[i].r)>>1;if(r<=mid) update(lson,l,r,w);else if(l>mid ) update(rson,l,r,w);else{update(lson,l,mid,w);update(rson,mid+1,r,w);}push_up(i); }ll query(int i,int aim) {if(tr[i].l==tr[i].r&&tr[i].l==aim){return tr[i].w;}push_down(i);int mid=(tr[i].l+tr[i].r)>>1;if(aim<=mid) return query(lson,aim);else return query(rson,aim); }ll getans(int u,int v) {int lca=LCA(u,v);ll sum1,sum2,sum3;sum1=query(1,L[u]); sum2=query(1,L[v]);sum3=query(1,L[lca]);return sum1+sum2-sum3*2; }int main() {int T;int u,v,op;ll w;scanf("%d",&T);while(T--){scanf("%d %d",&n,&q);init();for(int i=1;i<=n;i++){scanf("%d %d %lld",&u,&v,&w);add(u,v,w,i);add(v,u,w,i);ww[i]=w;}dfs1(1,-1);/// 第一遍dfs 先找到环中的任意一条边for(int i=1;i<=tot;i++){ /// 给边打上标记if((edge[i].u==uu&&edge[i].v==vv)||(edge[i].u==vv&&edge[i].v==uu)){edge[i].f=1;idd=edge[i].id;cost=edge[i].w;}}dfs2(1,0);/*cout<<"dfn "<<dfn<<endl;cout<<uu<<" *** "<<vv<<endl;for(int i=1;i<=n;i++){cout<<"l "<<L[i]<<" r "<<R[i]<<endl;}*/init_RMQ(dfn);build(1,1,n); /// 以dfs的遍历出的 L,R 建树 那么接下来就是一个区间更新,单点查询的问题了for(int i=1;i<=n;i++){if(i==idd) continue;u=to[i];update(1,L[u],R[u],ww[i]);}/*for(int i=1;i<=n;i++){ll tmp=query(1,L[i]);cout<<" dis "<<tmp<<endl;}*/while(q--){scanf("%d %d",&u,&v);ll ans=getans(u,v);ans=min(ans,getans(uu,u)+getans(vv,v)+cost); /// 经过标记的路的两个不同的方向。ans=min(ans,getans(uu,v)+getans(vv,u)+cost);printf("%lld\n",ans);}}return 0; }
View Code
转载于:https://www.cnblogs.com/shuaihui520/p/10439993.html
CF :K 一个含n条边的带权无向连通图,q次查询,每次查询两点间的最短距离。...相关推荐
- python不放回抽样_Python实现一个带权无回置随机抽选函数的方法
需求 有一个抽奖应用,从所有参与的用户抽出K位中奖用户(K=奖品数量),且要根据每位用户拥有的抽奖码数量作为权重. 如假设有三个用户及他们的权重是: A(1), B(1), C(2).希望抽到A的概率 ...
- 一个含n个顶点和e条弧的有向图以邻接矩阵表示法为存储结构,则计算该有向图中某个顶点出度的时间复杂度为
一个含n个顶点和e条弧的有向图以邻接矩阵表示法为存储结构,则计算该有向图中某个顶点出度的时间复杂度为( ) A.O(n) ...
- 代码资源网整站完整代码,基于ripro9.0定制开发,含572条精品资源数据
许多网友都想搭建一个资源网站,有些网友购买网站vip会员,然后再每天搬运代码资源再整理上传到自己的网站上去,实在太麻烦太辛苦. 鉴于此种需求,本人决定把本站到目前为止的数据整体打包,分享给大家,让大家 ...
- 分段函数是不是一定初等函数_查漏补缺问题64:一个含多参数分段函数的连续性与可导性讨论...
一个含多参数分段函数的连续性与可导性讨论 题目: 设, 定义函数 (1) 讨论当满足什么条件时,函数在0点连续. (2) 讨论当满足什么条件时,函数在0点可导. (3) 讨论当满足什么条件时,函数的导 ...
- Java黑皮书课后题第4章:*4.5(几何:正多边形的面积)正多边形是一个具有n条边的多边形,它每条边的长度都相等,而且所有角的度数也相等。编写程序,提示用户数输入边个数和边长,然后显示它的面积
*4.5(几何:正多边形的面积)正多边形是一个具有n条边的多边形,它每条边的长度都相等,而且所有角的度数也相对.编写程序,提示用户数输入边个数和边长,然后显示它的面积 题目 题目概述 运行示例 代码 ...
- bootstrap 导航菜单 折叠位置_教大家如何编写一个网页导航条
导航条简单地说就是对你整个网站模块的简单介绍,你可以直接点击导航条某一个按钮或板块便可进入其相应的界面,如:网页.新闻.贴吧等 .在企业网站上,导航条上常见的有:产品介绍,公司简介,最新产品,联系我们 ...
- SQL 拼接多个字段的值一个字段多条记录的拼接
例如student表: studentID studentName studentScore 01 Alice 90 02 Bill 95 03 Cindy 100 一.拼接多个字段的值 select ...
- 【408计算机考研】|【2018统考真题-41】| 给定一个含 n(n≥1)个整数的数组,请设计一个在时间上尽可能高效的算法,找出数组中未出现的最小正整数
目录 一.题目 二.解答 三.测试数据 一.题目 给定一个含 n(n≥1)个整数的数组,请设计一个在时间上尽可能高效的算 法,找出数组中未出现的最小正整数.例如,数组{-5, 3, 2, 3}中未 ...
- 给定一个含n(n≥1)个整数的数组,请设计一个在时间上尽可能高效的算法,找出数组中未出现的最小正整数。
笔者初涉<算法设计与分析>这门专业课,在做一些算法设计题的过程中遇到一些小感悟,特此记录和大家分享. 下面直接给出算法题目: 给定一个含n(n≥1)个整数的数组,请设计一个在时间上尽可能高 ...
最新文章
- springboot获取resources路径_Docker构建SpringBoot应用
- CTFshow php特性 web112
- IDEA创建方法时快速添加注释
- LeetCode 2 Keys Keyboard
- DefaultSingletonBeanRegistry 的registerDependentBean()方法对属性注入
- C语言数组查找(线性查找 折半查找)
- 使用LazZiya.ExpressLocalization开发多语言ASP.NET Core 2.x项目
- android里build报错怎么办,Android Studio 当build时候出错解决办法
- SQL Server 公用表表达式(CTE)
- 组织结构流程图模板分享
- java投票小程序_一个实现不记名投票的小程序
- 测试人收入情况大曝光,你的收入在什么水平
- 【七天实战微信小程序】任务清单
- School:1靶机
- python 构造函数里的同名变量_Python22个构造函数法-助力数据挖掘与分析
- 我的Photoshop大师之路(五)
- 抖音取图小程序,同款抖音壁纸,表情包小程序搭建
- 认识Lambda表达式
- 如何提升权限运行远程桌面客户端?
- esp32-C3学习笔记(1)微信配网
热门文章
- MyEclipse for Windows 关于 java、jsp、xml、js、html 等文件的注释快捷键及注释格式介绍
- linux内核cpu负载计算,CPU 负载 — The Linux Kernel documentation
- 将一个文件夹的文件复制到另一个文件夹
- matlab 返回变量类型的命令,MATLAB主要命令汇总
- 取得二进制最右面为1的数
- 华为配备鸿蒙系统的手机,华为P50/新平板双双来袭!全球首发鸿蒙系统:配置都非常强悍...
- 机智云代码移植_IoT开发者 | 基于STM32F103的机智云宠物屋外加4路继电器开源教程...
- concat合并的数组会有顺序么_JS 数组操作 记录 笔记
- yili邮箱服务器配置,手把手教 个人SMTP服务器的配置 -电脑资料
- linux内核编译如何选择cpu类型,Ubuntu内核编译和CPU Hot-Plug特性配置全过程及遇到问题记录...