【算法每日一练]-图论(保姆级教程 篇5(LCA,最短路,分层图)) #LCA #最短路计数 #社交网络 #飞行路线 # 第二短路

今天讲最短路统计和分层图

目录

题目:LCA 

思路:

题目:最短路计数

思路:

题目:社交网络

思路:

题目:飞行路线 

思路:

题目:第二短路

思路:


        

        

题目:LCA 

        

思路:

        

非常明显了,之前就说过倍增迭代就是一个一个选区间使总长度达到 M(凑一个数),用不大于它最大的二的次幂,减去之后,再重复这个过程。所以LCA+倍增逼近是最快的。

                

#include<bits/stdc++.h> //最近公共祖先LCA P3379:给一棵数,求任意两点的LCA 
using namespace std;
const int maxn=500002;
int n,m,s,tot=0;
int head[maxn],d[maxn],p[maxn][21];//d存的是深度(deep),p[i][j]存的从i向上走2的j次方那么长的路径到的父节点
struct node{int v,next;}e[maxn*2];//存数要开两倍
void add(int u,int v){e[++tot]={v,head[u]};head[u]=tot;}     void dfs(int u,int fa)// 首先进行的预处理,将所有点的deep和p的初始值dfs出来
{d[u]=d[fa]+1; p[u][0]=fa;  //处理深度,父节点for(int i=1;(1<<i)<=d[u];i++)//i<log(d[u]) 处理每个u的st表p[u][i]=p[p[u][i-1]][i-1];for(int i=head[u];i;i=e[i].next){ //处理u的孩子的st表int v=e[i].v;if(v!=fa) dfs(v,u);//只能向下走,不能向上走}
}                              
int lca(int a,int b) //非常标准的lca查找(两次逼近)
{if(d[a]>d[b]) swap(a,b);   //保证a是在b结点上方(d[b]大)for(int i=20;i>=0;i--){if(d[a]<=d[b]-(1<<i)) b=p[b][i];//向上逼近(b向上移到和a同一个深度)}  if(a==b) return a;  //特判for(int i=20;i>=0;i--){if(p[a][i]==p[b][i]) continue; //向上逼近(A和B一起向上,不断逼近最下端的公共祖先)else a=p[a][i],b=p[b][i];     }return p[a][0];  //找出最后a值的数字
}
int main()
{int a,b;scanf("%d%d%d",&n,&m,&s);//n个结点,m次询问,s是树根编号for(int i=1;i<n;i++){scanf("%d%d",&a,&b);add(a,b); add(b,a); //无向图,要加两次              }dfs(s,0);for(int i=1;i<=m;i++){scanf("%d%d",&a,&b);printf("%d\n",lca(a,b));}return 0;
}

        

         

题目:最短路计数

                  

思路:

        

注意到每条路径的权值都是1,难怪结果会那么大。

        

dikjkstra和spfa版本最短路计数:
1,维护最短路时产生的:那就是映射关系(因为引入的是周围点,相当于ans[v]=ans[cur]*1)
2,新最短路:发现了新的最短路就相加

        
floyd版本最短路计数:
1,维护最短路时产生的:(因为引入的是任意点,故ans[i][j]=ans[i][k]*ans[k][j])
2,新最短路:发现了新的最短路就相加

、        

#include <bits/stdc++.h>
using namespace std;
typedef pair<int,int> pii;
const int N=1e6+5,M=2e6+5;
int mod=100003,n,m,tot=0;
int head[N],vis[N],dis[N],ans[N];
priority_queue<pii,vector<pii>,greater<pii>>Q;
struct node {int to;int next;}e[M*2];
void add(int u,int v){e[++tot]=(node){v,head[u]};head[u]=tot;}
void dijkstra(int s){memset(dis,0x3f,sizeof(dis));Q.push({0,s});dis[s]=0;ans[s]=1;while(!Q.empty()){int cur=Q.top().second;Q.pop();if(vis[cur])continue;//跳不跳无所谓,无非耗点时间vis[cur]=1;for(int i=head[cur];i;i=e[i].next){int v=e[i].to;if(dis[cur]+1<dis[v])dis[v]=dis[cur]+1,ans[v]=ans[cur],Q.push({dis[v],v});//映射最短路(路过此点可以变短,那么最短路就和它有关)else if(dis[cur]+1==dis[v])ans[v]+=ans[cur],ans[v]%=mod;//新最短路(发现了另外的最短路就相加)}}
}
int main(){cin>>n>>m;int x,y;for(int i=1;i<=m;i++){scanf("%d%d",&x,&y);add(x,y);add(y,x);}dijkstra(1);//spfa(1);for(int i=1;i<=n;i++){cout<<ans[i]<<'\n';}
}

                 

//spfa版本:这个版本更快!!!!
void spfa(int s){memset(dis,0x3f,sizeof(dis));queue<int>q;vis[s]=1;q.push(s);dis[s]=0;ans[s]=1;while(!q.empty()){int cur=q.front();q.pop();vis[cur]=0;for(int i=head[cur];i;i=e[i].next){int v=e[i].to;if(dis[cur]+1<dis[v]){dis[v]=dis[cur]+1;ans[v]=ans[cur];if(!vis[v])q.push(v),vis[v]=1;	}else if(dis[cur]+1==dis[v])ans[v]+=ans[cur],ans[v]%=mod;}}
}

        

        

题目:社交网络

                

思路:

        

点i的重要程度=∑从s到t的且经过i最短路条数/从s到t的最短路条数(s!=i,t!=i)

主要还是floyd算法,求出每个(i,j)对每个k的重要程度为ans[k]
求到某点时最短路径数:
1,只要最短路更新,那么最短路个数也要更新
2,如果发现了新的最短路,那么就相加
        

#include <bits/stdc++.h>
using namespace std;   
typedef long long ll;
const int N=110;
ll INF,dis[N][N],e[N][N];//e[i][j]表示(i,j)的最短路径数
double ans[N];//每个点的重要程度
int main(){int n,m;ll x,y,z;cin>>n>>m;memset(dis,0x7f,sizeof(dis));INF=dis[1][1];//初始化INF无穷大for(int i=1;i<=m;i++){scanf("%lld%lld%lld",&x,&y,&z);dis[x][y]=dis[y][x]=z;e[x][y]=e[y][x]=1;//初始化e[i][j]}for(int i=1;i<=n;i++)  dis[i][i]=0;//对角线为0,但是不写也对其余任何边都没有影响,写不写随你for(int k=1;k<=n;k++)for(int i=1;i<=n;i++)for(int j=1;j<=n;j++){if(dis[i][k]==INF||dis[k][j]==INF)continue;//有不通的就直接跳过if(dis[i][j]>dis[i][k]+dis[k][j]){dis[i][j]=dis[i][k]+dis[k][j];//每个边只会更新一次,即当前最优e[i][j]=e[i][k]*e[k][j];//只要最短路更新,则最短路对应的个数也要更新即可continue;}if(dis[i][j]==dis[i][k]+dis[k][j]){//找到了第二条最短路,就相加e[i][j]+=e[i][k]*e[k][j];}}for(int k=1;k<=n;k++)for(int i=1;i<=n;i++)for(int j=1;j<=n;j++){if(i==j||j==k||i==k)continue;if(dis[i][j]==dis[i][k]+dis[k][j])//对k遍历每个(i,j)ans[k]+=(1.0*e[i][k]*e[k][j])/e[i][j];}for(int i=1;i<=n;i++)printf("%0.3f\n",ans[i]);
}

       

         

题目:飞行路线 

        

                 

思路:

        

 一个图中任意两个点都可以权值变成0,最多有k次,我们常常建立k层的分层图,相邻层所有点建立权值为0的立体边,然后跑最短路即可
        

#include <bits/stdc++.h> 
using namespace std;
int cnt,head[110005];
int dis[110005];
bool vis[110005]; //标记当前白点,如果不想用vis,也可以判断取出元素的dis和dis数组中值是否一样
priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>> > Q; //堆优化(first是值,second是下标)
struct Edge{ int to,w,next;}e[2500001];
void add(int u,int v,int w) { e[++cnt]=(Edge){v,w,head[u]}; head[u]=cnt;}
void Dijkstra(int s)//dijktra+堆优化
{memset(dis,0x3f,sizeof(dis));dis[s]=0;Q.push(make_pair(0,s));while(!Q.empty())  //必须用empty, size是求大小的,会慢一些 !!!{int u=Q.top().second; Q.pop();if(vis[u]) continue; //已经是白点的就跳过vis[u]=1; //标记成白点for(int i=head[u];i;i=e[i].next){int v=e[i].to,w=e[i].w;if(dis[v]>dis[u]+w) dis[v]=dis[u]+w,Q.push(make_pair(dis[v],v));}}    
}int main()
{int n,m,k,s,t;cin>>n>>m>>k>>s>>t; //城市数,航线数,免费次数,起始城市号,终点城市号int u,v,c;for(int i=0;i<m;++i){cin>>u>>v>>c;//两个城市航线,费用for(int j=0;j<=k;++j){//建立每层图add(u+j*n,v+j*n,c);add(v+j*n,u+j*n,c);if(j!=k){//第k层下面没有了,就别建了add(u+j*n,v+(j+1)*n,0); //分层图:所有相邻层间:上下层u,v的权值为0add(v+j*n,u+(j+1)*n,0);}}}for(int i=1;i<=k;++i){add(t+(i-1)*n,t+i*n,0);}//处理奇葩数据Dijkstra(s);printf("%d",dis[t+k*n]);return 0;
}

         

         

题目:第二短路

                 

思路:

#include<bits/stdc++.h>
using namespace std;   
typedef pair<int,int> pii;
const int N=5005,M=100005;
int n,m,tot,flag;
int head[N],d1[N],d2[N],vis[N];
priority_queue<pii,vector<pii>,greater<pii> > Q;
struct node{int to;int w;int next;}e[M*2];
void add(int u,int v,int w){e[++tot]=(node){v,w,head[u]};head[u]=tot;}
void dijkstra(int s){memset(d1,0x3f,sizeof(d1));//d1存放第一短路memset(d2,0x3f,sizeof(d2));//d2存放第二短路Q.push(make_pair(0,s));d1[s]=0;while(!Q.empty()){int cur=Q.top().second;Q.pop();if(vis[cur])continue;//vis数组可有可无,即便旧白点引入也掀不起变化,无非多走了几步vis[cur]=1;for(int i=head[cur];i;i=e[i].next){int v=e[i].to,w=e[i].w;flag=0;if(d1[cur]+w<d1[v])d2[v]=d1[v],d1[v]=d1[cur]+w,flag=1;//维护最短路,更新前的最短路就是次短路if(d1[cur]+w>d1[v]&&d1[cur]+w<d2[v])d2[v]=d1[cur]+w,flag=1;//最短路没有变化,更新次短路if(d2[cur]+w<d2[v])d2[v]=d2[cur]+w,flag=1;//维护次短路,如果d2[s]初始化成0,那么这个地方就出问题了if(flag)Q.push(make_pair(d1[v],v));}}
}
int main(){cin>>n>>m;int u,v,w;for(int i=1;i<=m;i++){scanf("%d%d%d",&u,&v,&w);add(u,v,w);add(v,u,w);}dijkstra(1);cout<<d2[n];
}

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

electron使用better-sqlite3打包失败(electron打包有进程没有界面)

remove *\chrome_100_percent.pak: Access is denied. 解决&#xff1a; 管理员权限执行&#xff1a;taskkill /IM 你的进程名.exe /F&#xff0c;再次执行build electron使用better-sqlite3打包后有进程没有界面 原因是代码及依赖包安装有误&#xff0c;模块丢失。主要分享的…

Python开源项目GPEN——人脸重建(Face Restoration),模糊清晰、划痕修复及黑白上色的实践

无论是自己、家人或是朋友、客户的照片&#xff0c;免不了有些是黑白的、被污损的、模糊的&#xff0c;总想着修复一下。作为一个程序员 或者 程序员的家属&#xff0c;当然都有责任满足他们的需求、实现他们的想法。除了这个&#xff0c;学习了本文的成果&#xff0c;或许你还…

腾讯云新用户优惠活动有哪些可以参加?腾讯云新人服务器优惠活动

腾讯云作为国内领先的云服务提供商&#xff0c;不仅为用户提供稳定可靠的云服务器&#xff0c;还为新用户带来了一系列的优惠活动和代金券&#xff0c;以降低购买成本&#xff0c;提高业务效益。在这里&#xff0c;我们将为您详细介绍腾讯云服务器的新人优惠活动及代金券&#…

Git企业开发级讲解(四)

&#x1f4d8;北尘_&#xff1a;个人主页 &#x1f30e;个人专栏:《Linux操作系统》《经典算法试题 》《C》 《数据结构与算法》 ☀️走在路上&#xff0c;不忘来时的初心 文章目录 一、理解分⽀二、创建分支三、切换分⽀四、合并分⽀五、删除分⽀六、合并冲突七、分⽀管理策略…

pythom导出mysql指定binlog文件

要求 要求本地有py环境和全局环境变量 先测试直接执行binlog命令执行命令 Windows 本地直接执行命令 # E:\output>E:\phpstudy_pro\Extensions\MySQL5.7.26\bin\mysqlbinlog binglog文件地址 # --no-defaults 不限制编码 # -h mysql链接地址 # -u mysql 链接名称 # -p m…

word文档转换为ppt文件,怎么做?

大家是否会遇到需要将word文档转换为ppt文件的情况&#xff1f;除了反反复复粘贴复制以外&#xff0c;还有其他方法可以转换文件格式&#xff0c;今天给大家分享word转换ppt方法。 首先我们先将word文件打开大纲模式 然后我们将文中的大标题设置为1级标题&#xff0c;副标题设…

flutter仿支付宝余额宝年化收益折线图

绘制&#xff1a; 1.在pubspec.yaml中引入&#xff1a;fl_chart: 0.55.2 2.绘制&#xff1a; import package:jade/utils/JadeColors.dart; import package:util/easy_loading_util.dart; import package:fl_chart/fl_chart.dart; import package:flutter/material.dart; impo…

Leetcode—142.环形链表II【中等】

2023每日刷题&#xff08;三十三&#xff09; Leetcode—142.环形链表II 实现代码 /*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/ struct ListNode *detectCycle(struct ListNode *head) {struct ListNode* …

Stable Diffusion - StableDiffusion WebUI 软件升级与扩展兼容

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/134463035 目前&#xff0c;StableDiffusion WebUI 的版本是 1.6.0&#xff0c;同步更新 controlnet、tagcomplete、roop、easy-prompt-selector等…

vmware安装MacOS以及flutter遇到的问题

安装过程&#xff1a;参考下面的文章 链接&#xff1a; 虚拟机VMware安装苹果系统macOS&#xff0c;超级详细教程&#xff0c;附文件下载&#xff0c;真教程&#xff01;&#xff01; 无限重启情况&#xff1a; &#xff08;二&#xff09; 配置虚拟机找到你的虚拟机安装文件…

Vite -静态资源处理 - SVG格式的图片

特点 Vite 对静态资源是开箱即用的。 无需做特殊的配置。项目案例 项目结构 study-vite| -- src| -- assets| -- bbb.svg # 静态的svg图片资源| -- index.html # 主页面| -- main.js # 引入静态资源| -- package.json # 脚本配置| -- vite.co…

景联文科技入选量子位智库《中国AIGC数据标注产业全景报告》数据标注行业代表机构

量子位智库《中国AIGC数据标注产业全景报告》中指出&#xff0c;数据标注处于重新洗牌时期&#xff0c;更高质量、专业化的数据标注成为刚需。未来五年&#xff0c;国内AI基础数据服务将达到百亿规模&#xff0c;年复合增长率在27%左右。 基于数据基础设施建设、大模型/AI技术理…

安装应用与免安装应用差异对比

差异 安装的程序和免安装的应用程序之间有以下几个方面的差别&#xff1a; 安装过程&#xff1a;安装的程序需要通过一个安装程序或安装脚本进行安装。这个过程通常会将应用程序的文件和依赖项复制到指定的目录&#xff0c;并进行一些配置和注册操作。免安装的应用程序则不需要…

Apache Airflow (八) :DAG任务依赖设置

&#x1f3e1; 个人主页&#xff1a;IT贫道_大数据OLAP体系技术栈,Apache Doris,Clickhouse 技术-CSDN博客 &#x1f6a9; 私聊博主&#xff1a;加入大数据技术讨论群聊&#xff0c;获取更多大数据资料。 &#x1f514; 博主个人B栈地址&#xff1a;豹哥教你大数据的个人空间-豹…

nginx学习(1)

一、下载安装NGINX&#xff1a; 先安装gcc-c编译器 yum install gcc-c yum install -y openssl openssl-devel&#xff08;1&#xff09;下载pcre-8.3.7.tar.gz 直接访问&#xff1a;http://downloads.sourceforge.net/project/pcre/pcre/8.37/pcre-8.37.tar.gz&#xff0c;就…

【Windows 开发环境配置——NVIDIA 篇】CUDA、cuDNN、TensorRT 三件套安装

CUDA 从CUDA Toolkit Archive下载相应版本的离线安装包&#xff0c;这里以11.7为例。 打开安装包&#xff0c;在安装选项选择自定义模式&#xff0c;点击下一步。 在自定义安装选项中&#xff0c;仅选择CUDA组件&#xff08;其中Nsight相关组件用于代码调试与性能分析&#xff…

JVM bash:jmap:未找到命令 解决

如果我们在使用JVM的jmap命令时遇到了"bash: jmap: 未找到命令"的错误&#xff0c;这可能是因为jmap命令没有在系统的可执行路径中。 要解决这个问题&#xff0c;可以尝试以下几种方法&#xff1a; 1. 检查Java安装&#xff1a;确保您已正确安装了Java Development …

stable diffusion十七种controlnet详细使用方法总结

个人网站&#xff1a;https://tianfeng.space 前言 最近不知道发点什么&#xff0c;做个controlnet 使用方法总结好了&#xff0c;如果你们对所有controlnet用法&#xff0c;可能了解但是有点模糊&#xff0c;希望能对你们有用。 一、SD controlnet 我统一下其他参数&#…

大数据可视化是什么?

大数据可视化是将海量数据通过视觉方式呈现出来&#xff0c;以便于人们理解和分析数据的过程。它可以帮人们发现数据之间的关系、趋势和模式&#xff0c;并制定更明智的决策。大数据可视化通常通过图形、图表、地图和仪表盘等视觉元素来呈现数据。这些元素具有直观、易理解的特…