当前位置: 首页 > 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.lryc.cn/news/597122.html

相关文章:

  • 【图论,拓扑排序】P1347 排序
  • 算法竞赛备赛——【图论】最小生成树
  • Modbus协议详解与c#应用
  • 算法竞赛备赛——【图论】拓扑排序
  • CI/CD与DevOps集成方法
  • python在windows电脑找回WiFi密码
  • 【按下电源键后,电脑里发生了什么?——BIOS:启动世界的“第一把钥匙”】
  • C++编程学习(第14天)
  • [Mediatek] MTK openwrt-21.02 wifi 没启动问题
  • 详述消息队列kafka
  • 【通识】手机和芯片相关
  • LazyVim 加载顺序
  • MySQL金融级数据一致性保障:从原理到实战
  • 数据持久化--PlayerPrefs
  • Hexo - 免费搭建个人博客06 - 安装、切换主题Butterfly
  • 基于Java实现DFT、FFT,并绘制波形图和频谱图,音频播放频谱或波形图
  • 内积(Inner Product)和余弦相似度区别
  • MATLAB近红外光谱分析:MATLAB编程+BP神经网络+SVM+随机森林+遗传算法+变量降维+卷积神经网络等
  • 以 “有机” 重构增长:云集从电商平台到健康生活社区的跃迁
  • 零工合规挑战:盖雅以智能安全体系重构企业用工风控
  • 认识linux进程内存布局以及与命令行参数和环境变量的关系
  • 如何在VS code里使用SQLtool连接上WSL上的MySQL服务
  • 【软件系统架构】系列七:物联网云平台系统性能深入解析
  • 线性神经网络(深度学习-李沐-学习笔记)
  • 探索大语言模型(LLM):提升 RAG 性能的全方位优化策略
  • 我考PostgreSQL中级专家证书二三事
  • 论文略读:REMEDY: RECIPE MERGING DYNAMICS IN LARGE VISION-LANGUAGE MODELS
  • vue3笔记(2)自用
  • 微软2025教育AI报告:教育群体采用AI的比例显著提升
  • 技术速递|使用 Semantic Kernel 与 A2A 协议构建多智能体解决方案