图论复习P
时间:2020-05-09
本文章向大家介绍图论复习P,主要包括图论复习P使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
题意:n个点m条边,m-n≤20,给你q组询问,每组询问两个点之间的最短路径
分析:如果是n个点,n-1条边,显然lca就能完美解决
如果加一条边,显然需要把通过该边的路径与lca结果取最小值
但如何求通过该边的路径的最小值呢?
可以转化成通过该边两端点的路径的最小值
而通过端点的路径的最小值可以以端点跑个spfa或dij,求出其到所有节点的距离
那么从x到y经过点p的最短路径就可以表示为dis[p][x]+dis[p][y]
当然,这里需要跑spfa的点最多只有42个,也就是在树的基础上加了42条边
只需要将其取个最小值即可
代码:
#include<cstdio> #include<algorithm> #include<cstring> #include<queue> using namespace std; #define ll long long const int maxm=2e5+1; const int maxp=3e1+1; const int maxn=1e5+1; const int maxlg=2e1+1; struct Node { int to,next,val; }e[maxm<<1]; struct edge { int x,y,z; }a[maxm]; int head[maxn]; ll dis[maxp<<1][maxn]; bool vis[maxn]; int deep[maxn]; bool isp_e[maxm]; bool isp_d[maxn]; int fa[maxn][maxlg]; ll val[maxn][maxlg]; int pp[maxp<<1]; int cnt,n,m; void add(int x,int y,int z) { e[++cnt].val=z; e[cnt].to=y; e[cnt].next=head[x]; head[x]=cnt; } void spfa(int x,int p) { deque<int> q;q.push_back(x),dis[p][x]=0ll; while(!q.empty()) { int now=q.front();q.pop_front(); vis[now]=0; for(int i=head[now];i;i=e[i].next) { int v=e[i].to; if(dis[p][v]>dis[p][now]+(ll)e[i].val) { dis[p][v]=dis[p][now]+(ll)e[i].val; if(!vis[v]) { vis[v]=1; if(!q.empty()&&dis[p][v]<dis[p][q.front()]) q.push_front(v); else q.push_back(v); } } } } } void lca() { for(int i=1;i<maxlg;i++) for(int j=1;j<=n;j++) { int now=fa[j][i-1]; fa[j][i]=fa[now][i-1]; val[j][i]=val[j][i-1]+val[now][i-1]; } } ll ask(int x,int y) { if(deep[x]<deep[y]) swap(x,y); int now=deep[x]-deep[y]; ll ans=0; for(int i=0;now;i++,now>>=1) if(now&1) ans+=val[x][i],x=fa[x][i]; if(x==y) return ans; for(int i=maxlg-1;i>=0;i--) { if(fa[x][i]!=fa[y][i]) { ans+=val[x][i]+val[y][i]; x=fa[x][i],y=fa[y][i]; } } return ans+val[x][0]+val[y][0]; } void dfs(int x,int fax) { vis[x]=1; for(int i=head[x];i;i=e[i].next) { int v=e[i].to; if(!vis[v]) { fa[v][0]=x; val[v][0]=(ll)e[i].val; deep[v]=deep[x]+1; isp_e[i-1>>1]=1; dfs(v,x); } } } int main() { int q,x,y,z; memset(dis,0x3f,sizeof(dis)); scanf("%d%d",&n,&m); for(int i=0;i<m;i++) { scanf("%d%d%d",&x,&y,&z); add(x,y,z);add(y,x,z); a[i].x=x,a[i].y=y,a[i].z=z; } dfs(1,-1); memset(vis,0,sizeof(vis)); for(int i=0;i<m;i++) if(!isp_e[i]) isp_d[a[i].x]=isp_d[a[i].y]=1; int pnum=0; for(int i=1;i<=n;i++) if(isp_d[i]) pp[++pnum]=i,spfa(i,pnum); lca(); scanf("%d",&q); while(q--) { scanf("%d%d",&x,&y); ll ans=ask(x,y); for(int i=1;i<=pnum;i++) ans=min(ans,dis[i][x]+dis[i][y]); printf("%lld\n",ans); } return 0; }
原文地址:https://www.cnblogs.com/lin4xu/p/12856678.html
- 【Go 语言 redis内存数据库存储 demo】
- linux下基本操作记录mongodb
- ClassLoader究竟为何物?
- Oracle应用实战八(完结)——存储过程、函数+对象曹组
- 动态代理模式原理
- SQL可以正常用,但cmd启动不了mysql,报错[ERROR] unknown variable ;basedir=....问题
- Percona-toolkit的安装和配置(r8笔记第86天)
- 分布式服务框架 Zookeeper
- python--类方法、对象方法、静态方法
- Go语言内存分配器的实现
- Go 语言 数据库操作之链接数据库实现
- 对于tnsping的连接超时的功能补充(r9笔记第3天)
- struts2拦截器源码分析
- Go语言学习(一):hello world
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Android巧用XListView实现万能下拉刷新控件
- Android获取其他应用中的assets资源
- Android自定义动态壁纸开发详解
- VsCode插件koroFileHeader一键添加文件头部注释
- 强大的 Stream API(一)
- python3 配置logging日志类的操作
- 你对CSS权重真的足够了解吗?
- python opencv实现图片缺陷检测(讲解直方图以及相关系数对比法)
- Js 的事件循环(Event Loop)机制以及实例讲解
- 你不知道的js中关于this绑定机制的解析[看完还不懂算我输]
- 解决Django部署设置Debug=False时xadmin后台管理系统样式丢失
- 算法-查找斐波纳契数列中第 N 个数
- 在python中修改.properties文件的操作
- Django Xadmin多对多字段过滤实例
- 算法-姓名去重