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

图论的题目整合(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.xdnf.cn/news/16055.html

相关文章:

  • 欧盟网络安全标准草案EN 18031详解
  • ESP32-S3学习笔记<5>:SPI的应用
  • Redis 的事务机制是怎样的?
  • freqtrade在docker运行一个dryrun实例
  • UI自动化测试实战
  • mysql什么时候用char,varchar,text,longtext
  • odoo欧度小程序——添加用户
  • Fluent许可与硬件绑定的解决方法
  • Spring Data Redis 从入门到精通:原理与实战指南
  • C++刷题 - 7.23
  • kettle 8.2 ETL项目【一、初始化数据库及介绍】
  • 【MySQL】MySQL 索引详解
  • UniappDay01
  • 计算机毕设分享-基于SpringBoot的房屋租赁系统(开题报告+源码+Lun文+开发文档+数据库设计文档)
  • 【Spring Cloud Gateway 实战系列】进阶篇:过滤器高级用法、动态路由配置与性能优化
  • 【计算机网络】正/反向代理服务器,有状态/无状态应用
  • 漏洞生命周期管理:从发现到防护的全流程方案
  • AI产品经理面试宝典第48天:产品设计与用户体验优化策略
  • log4j2漏洞
  • 无人机光伏巡检误检率↓78%!陌讯多模态融合算法实战解析
  • Linux Debian操作系统、Deepin深度操作系统手动分区方案参考
  • 【数据结构初阶】--树和二叉树先导篇
  • C++题解 P2288 家谱(gen)
  • 2025.7.15vlan作业
  • 1553B心得总结
  • 对象\数组\Map按属性值排序迭代器
  • 达索×杰克×安托:开启服装智造“新宇宙”
  • 密码学中的概率论与统计学:从频率分析到现代密码攻击
  • 不止于“亮”:一盏智慧路灯的技术进化史——塔能科技用“落地性”定义行业标准
  • Python 程序设计讲义(9):Python 的基本数据类型——复数