当前位置: 首页 > news >正文

图论的题目整合(Dijkstra)

前置知识:
Dijkstra

题目1

AT_abc070_d [ABC070D] Transit Tree Path
由于点 KKK 是固定的,并且是无向图(题目说是树),其实可以理解为求点 KKK 到点 xjx_jxj 的最短路加上点 KKK 到点 yjy_jyj 的最短路。

由于边权 cic_ici 的范围是 1≤ci≤1091\le c_i\le10^91ci109,没有负数,所以用 Dijkstra 以 KKK 为起点跑最短路。

#include<bits/stdc++.h>
#define int long long
#define endl putchar('\n')
using namespace std;
const int N=1e6+5;
int read(){int x=0,f=1;char c=getchar();while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+c-'0',c=getchar();return x*f;
}
void print(int x){if(x<0)putchar('-'),x=-x;if(x<10){putchar(x+'0');return;}print(x/10);putchar(x%10+'0');
}
int n,m,k;
int T;
struct node{int to,dis;friend bool operator <(node a,node b){return a.dis>b.dis;}
};
priority_queue<node>q;
vector<node>a[N];
int dis[N];
int vis[N];
void dij(){for(int i=1;i<=n;i++)dis[i]=1e18;dis[k]=0;q.push(node{k,0});while(!q.empty()){node t=q.top();q.pop();int x=t.to;if(vis[x])continue;vis[x]=1;for(int i=0;i<a[x].size();i++){int y=a[x][i].to;int z=a[x][i].dis;dis[y]=min(dis[y],dis[x]+z);if(!vis[y])q.push(node{y,dis[y]});}}
}
signed main(){n=read();m=n-1;while(m--){int u=read(),v=read(),w=read();a[u].push_back(node{v,w});a[v].push_back(node{u,w});}T=read(),k=read();dij();while(T--){int x=read(),y=read();print(dis[x]+dis[y]);endl;}
}

题目2

题目描述
给出 NNN 个结点,MMM 条边的有向图,结点从 111MMM 编号。
求最少将多少条边反向,才能至少有一条从 111NNN 的路径?
例如,下图中把 3⟶2,7⟶43\longrightarrow2,7\longrightarrow432,74 这两条边反向,可以得到一条从 111777 的路径。
也可以把 6⟶2,5⟶6,7⟶56\longrightarrow2,5\longrightarrow6,7\longrightarrow562,56,75 这三条边反向,得到一条从 111777 的路径。
显然前者更优。
输入格式
111 行:NNNMMM
接下来 MMM 行,每行 222 个整数 u,vu, vu,v,表示一条有向边。
输出格式
111 行:111 个整数,表示答案。
如果无法实现从 111NNN,输出 −1-11

反转一条边需要一次,所以可以建一条翻转后的边但是边权为 111,再对图跑最短路(或者01BFS)。

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+5;
int read(){int x=0,f=1;char c=getchar();while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+c-'0',c=getchar();return x*f;
}
void print(int x){if(x<0)putchar('-'),x=-x;if(x<10){putchar(x+'0');return;}print(x/10);putchar(x%10+'0');
}
void putstr(string s){for(char v:s)putchar(v);
}
int n,m;
struct node{int to,dis;friend bool operator<(node a,node b){return a.dis>b.dis;}
};
vector<node>a[N];
int dis[N];
int vis[N];
priority_queue<node>q;
signed main(){n=read(),m=read();while(m--){int u=read(),v=read();a[u].push_back(node{v,0});a[v].push_back(node{u,1});}for(int i=1;i<=n;i++)dis[i]=1e18;q.push(node{1,0});dis[1]=0;while(!q.empty()){int x=q.top().to;q.pop();if(vis[x])continue;vis[x]=1;for(int i=0;i<a[x].size();i++){int y=a[x][i].to;int z=a[x][i].dis;if(dis[y]>dis[x]+z)dis[y]=dis[x]+z;if(!vis[y])q.push(node{y,dis[y]});}}if(dis[n]>=1e18)dis[n]=-1;print(dis[n]);
}

题目3

题目描述
给出一个有 nnn 个顶点 mmm 条边的无向连通图,每条边有一个长度 LiL_iLi,结点编号从 1∼n1\sim n1n
求从起点 111 到终点 nnn 的最短路径的长度及其途经的各结点。
输入格式
111 行:222 个整数 nnnm(n≤200,m≤10000)m(n\le200,m\le10000)m(n200,m10000)
接下来 mmm 行,每行 333 个整数 x,y,Lix, y, L_ix,y,Li,表示结点 xxxyyy 之间的长度为 LiL_iLi
输出格式
111 行:111 个整数,表示 111nnn 的最短距离。
222 行:若干个整数,表示 111nnn 的最短路径经过的各结点。

根据单源最短路径改,每次找到更优的路径就标记一下它下一个点的上一个点,注意不能标记下一个点来记录路径,因为起点不止能到终点 nnn,但是终点 nnn 只能是起点到达。

#include<bits/stdc++.h>
#define int long long
//#define lc p<<1
//#define rc p<<1|1
//#define lowbit(x) x&-x
#define psp putchar(' ')
#define endl putchar('\n')
using namespace std;
const int N=1e6+5;
int read(){int x=0,f=1;char c=getchar();while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+c-'0',c=getchar();return x*f;
}
void print(int x){if(x<0)putchar('-'),x=-x;if(x<10){putchar(x+'0');return;}print(x/10);putchar(x%10+'0');
}
void putstr(string s){for(char v:s)putchar(v);
}
int n,m,s;
int T;
struct node{int to,dis;friend bool operator <(node a,node b){return a.dis>b.dis;}
};
priority_queue<node>q;
vector<node>a[N];
int dis[N];
int vis[N];
int pre[N];
void dij(){for(int i=1;i<=n;i++)dis[i]=INT_MAX;dis[1]=0;q.push(node{1,0});while(!q.empty()){node t=q.top();q.pop();int x=t.to;if(vis[x]==1)continue;vis[x]=1;for(int i=0;i<a[x].size();i++){int y=a[x][i].to;int z=a[x][i].dis;if(dis[y]>dis[x]+z){dis[y]=dis[x]+z;pre[y]=x;}if(vis[y]==0)q.push(node{y,dis[y]});}}
}
signed main(){n=read(),m=read();for(int i=1;i<=m;i++){int u=read(),v=read(),w=read();a[u].push_back(node{v,w});a[v].push_back(node{u,w});}dij();print(dis[n]),endl;stack<int>t;while(n){t.push(n);n=pre[n];}while(!t.empty()){print(t.top()),psp;t.pop();}
}

题目4

题目描述
N(1≤N≤1000)N(1\le N\le1000)N(1N1000) 头牛要去参加一场在编号为 x(≤x≤N)x(\le x\le N)x(xN) 的牛的农场举行的派对。有 M(1≤M≤100000)M(1\le M\le 100000)M(1M100000) 条有向道路,每条路长 Ti(1≤Ti≤100)T_i(1\le T_i\le100)Ti(1Ti100)
每头牛都必须参加完派对后回到家,每头牛都会选择最短路径。求这 NNN 头牛的最短路径(一个来回)中最长的一条的长度。 特别提醒:可能有权值不同的重边。
输入格式
111 行:333 个空格分开的整数 ;
2…M+12\ldots M+12M+1 行:333 个空格分开的整数 Ai,Bi,TiA_i,B_i,T_iAi,Bi,Ti,表示有一条从 AiA_iAiBiB_iBi 的路,长度为 TiT_iTi
输出格式
一行一个数,表示最长最短路的长度。

回家的最短路很简单,以 xxx 为起点跑 Dijkstra 就行了,但是图是有向图,去的路和回来的路不一样,难道以每个点为起点跑一遍 Dijkstra?其实可以用另一个邻接表存反向边,然后去的路就变成了回来的路,以 xxx 为起点对反图跑一遍最短路就行了。

#include<bits/stdc++.h>
#define int long long//#define lc p<<1
//#define rc p<<1|1
//#define lowbit(x) x&-x
#define psp putchar(' ')#define endl putchar('\n')using namespace std;
const int N=1e6+5;
const int M=1e3+5;
int read(){int x=0,f=1;char c=getchar();while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+c-'0',c=getchar();return x*f;
}
void print(int x){if(x<0)putchar('-'),x=-x;if(x<10){putchar(x+'0');return;}print(x/10);putchar(x%10+'0');
}
void putstr(string s){for(char v:s)putchar(v);
}
int n,m,k;
int T;
struct node{int to,dis;friend bool operator<(node a,node b){return a.dis>b.dis;}
};
vector<node>a[N];
vector<node>b[N];
int dis[N];
int dis2[N];
int vis[N];
priority_queue<node>q;
signed main(){//ios::sync_with_stdio(0);n=read(),m=read(),k=read();while(m--){int u=read(),v=read(),w=read();a[u].push_back(node{v,w});b[v].push_back(node{u,w});}for(int i=1;i<=n;i++)dis[i]=1e18;dis[k]=0;q.push(node{k,0});while(!q.empty()){int x=q.top().to;q.pop();if(vis[x])continue;vis[x]=1;for(int i=0;i<a[x].size();i++){int y=a[x][i].to;int z=a[x][i].dis;dis[y]=min(dis[y],dis[x]+z);if(!vis[y])q.push(node{y,dis[y]});}}for(int i=1;i<=n;i++)dis2[i]=1e18,vis[i]=0;dis2[k]=0;q.push(node{k,0});while(!q.empty()){int x=q.top().to;q.pop();if(vis[x])continue;vis[x]=1;for(int i=0;i<b[x].size();i++){int y=b[x][i].to;int z=b[x][i].dis;dis2[y]=min(dis2[y],dis2[x]+z);if(!vis[y])q.push(node{y,dis2[y]});}}int mx=0;for(int i=1;i<=n;i++)mx=max(mx,dis[i]+dis2[i]);print(mx);
}
http://www.dtcms.com/a/293486.html

相关文章:

  • 货车手机远程启动功能的详细使用步骤及注意事项
  • Elasticsearch 字段值过长导致索引报错问题排查与解决经验总结
  • git初始流程
  • [2025CVPR-小目标检测方向]基于特征信息驱动位置高斯分布估计微小目标检测模型
  • 什么是GCN?GCN与GNN有哪些区别?
  • SpringBoot与Vue实战:高效开发秘籍
  • 快手视觉算法面试30问全景精解
  • NumPy核心操作全攻略
  • YOLO12论文阅读:Attention-Centric Real-Time Object Detectors
  • SQLAlchemy 2.0简单使用
  • nodejs模块化
  • 闲庭信步使用图像验证平台加速FPGA的开发:第三十课——车牌识别的FPGA实现(2)实现车牌定位
  • XCKU035‑1SFVA784C Xilinx FPGA KintexUltraScale AMD
  • C# 类 封装 属性 练习题
  • 深度学习 --- 激活函数
  • 计算机底层入门 05 汇编学习环境通用寄存器内存
  • MDC(Mapped Diagnostic Context) 的核心介绍与使用教程
  • LINUX 722 逻辑卷快照
  • (Arxiv-2025)HiDream-I1:一种高效图像生成基础模型,采用稀疏扩散Transformer
  • 在PyCharm中复现LaneNet车道线检测模型
  • JavaScript 01 JavaScript 是什么
  • 医疗系统伪代码
  • Ctenos7最小化安装 可以ping通
  • MySQL InnoDB存储引擎深度解析:从原理到优化
  • 【JavaSE】JDBC和连接池学习笔记
  • k8s:利用helm离线部署consul v1.21.2
  • 【Altium Designer2025】电子设计自动化(EDA)软件——Altium Designer25版保姆级下载安装详细图文教程(附安装包)
  • @PostConstruct 注解
  • Python进阶第三方库之Numpy
  • Docker-compose:服务编排