我们可以把指挥部和哨所抽象为点,哨所与指挥部或者与哨所之间送信的时间看成两个点之间的边权。
题目要我们求出完成整个送信过程最短需要的时间,其中完成整个过程:要求指挥部也就是点1能到达其他哨所也也就是其它点。
所以我们要求出最短送信时间只要求出点1到其他点的最长时间即可,即求出每个点到点1的最短距离的最大值。
-
选择算法:可以看出本题数据不大,因此可以选择最简单的floyd算法
-
代码实现:
#include
#include
using namespace std;
const int =110;
int g[N][N],INF=0x3f3f3f3f;//用邻接矩阵存储边
int n,m;
int main()
{
cin>>n>>m;
memset(g,0x3f,sizeof g);
while(m–)
{
int a,b,c;
cin>>a>>b>>c;
g[a][b]=g[b][a]=min(g[a][b],c);//题目给定的是无向边
}
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
g[i][j]=min(g[i][j],g[i][k]+g[k][j]);
}//floyd算法
int res=0;
for(int i=2;i<=n;i++)
{
if(g[1][i]==INF) //如果有哨所到不了,则输出-1
{
cout<<-1;
return 0;
}
res=max(res,g[1][i]);//取所有点到源点最短距离的最大值即是题目所求
}
cout<<res;
}
题2:香甜的黄油
-
分析:题目的意思就是要我们找出一个点使得其他点到该点的最短距离之和最小。把牧场当成图上的点,牧场间的道路为图上的边。所以只需要对每个点求一次对其他点的最短路既可以。
-
选择算法:这里数据的范围我们可以选择spfa()算法时间复杂度一共为O(nm);
-
代码实现:
#include <bits/stdc++.h>
using namespace std;
const int N=810,M=3000,INF=0x3f3f3f3f;
int h[N],e[M],ne[M],w[M],idx;
int dist[N];
bool st[N];
int n,p,c;
int id[N];//存储每个牛所在的牧场编号
void add(int a,int b,int c)//存储每两个牧场的信息
{
e[idx]=b;
ne[idx]=h[a];
w[idx]=c;
h[a]=idx++;
}
int spfa(int x)
{
memset(dist,0x3f,sizeof dist);
dist[x]=0;
queue q;
q.push(x);
st[x]=true;
while(q.size())
{
int t=q.front();
q.pop();
st[t]=false;
for(int i=h[t];i!=-1;i=ne[i])
{
int j=e[i];
if(dist[j]>dist[t]+w[i])
{
dist[j]=dist[t]+w[i];
if(!st[j])
{
st[j]=true;
q.push(j);
}
}
}
}
int res=0;
for(int i=1;i<=n;i++)
{
int j=id[i];
if(dist[j]==INF) return INF;//该点不能到达所有点,回无穷大。
res+=dist[j];
}
return res;
}
int main()
{
memset(h,-1,sizeof h);
cin>>n>>p>>c;
for(int i=1;i<=n;i++) cin>>id[i];
while(c–)
{
int a,b,c;
cin>>a>>b>>c;
add(a,b,c);
add(b,a,c);//无向边
}
int res=INF;
for(int i=1;i<=p;i++) res=min(res,spfa(i));//对每个点求解到其他点最短距离的和,取最小值。
cout<<res;
}
题3:最小花费
-
分析:本题我们可以把每个人当做图中的点,每两个人转账需要的手续费当作图中的边权,题目要求我们求出(人)点A转账到(人)点B使B有100元,A初始的最少需要多少钱?我们可以逆向思考,只需要求出点B到点A最大距离之积res即可,然后用100除以res即得到A最少需要的费用。
-
选择算法:这里选择朴素版dijkstra算法演示,这里存边需要注意。
-
代码实现:
#include <bits/stdc++.h>
using namespace std;
const int N=2e3+10;
double g[N][N],dist[N];;//题目要求保留8位小数这里用double
int n,m;
int A,B;
bool st[N];
double dijkstra()
{
dist[A]=1;
for(int i=0;i<n;i++)
{
int t=-1;
for(int j=1;j<=n;j++)
if(!st[j]&&(t==-1||dist[t]<dist[j]))
t=j;
st[t]=true;
for(int j=1;j<=n;j++)
dist[j]=max(dist[j],dist[t]g[t][j]);//求最大距离乘积把’+‘改成’'即可
}
return dist[B];
}
int main()
{
cin>>n>>m;
while(m–)
{
int a,b,c;
cin>>a>>b>>c;
double z=(100.0-c)/100;//这里存入的边权用double题目给出的是扣除百分之几,我们存入的是减去扣除的还剩余的百分之几,便于计算。
g[a][b]=g[b][a]=max(g[a][b],z);
}
cin>>A>>B;
double res=dijkstra();
printf(“%.8lf”,100/res);
}
七.附录(四种解法模板,转载自AcWing)
1.朴素dijkstra算法
//时间复杂是 O(n2+m), n 表示点数,m 表示边数
int g[N][N]; // 存储每条边
int dist[N]; // 存储1号点到每个点的最短距离
bool st[N]; // 存储每个点的最短路是否已经确定
// 求1号点到n号点的最短路,如果不存在则返回-1
int dijkstra()
{
memset(dist, 0x3f, sizeof dist);
dist[1] = 0;
for (int i = 0; i < n - 1; i ++ )
{
int t = -1; // 在还未确定最短路的点中,寻找距离最小的点
for (int j = 1; j <= n; j ++ )
if (!st[j] && (t == -1 || dist[t] > dist[j]))
t = j;
// 用t更新其他点的距离
for (int j = 1; j <= n; j ++ )
dist[j] = min(dist[j], dist[t] + g[t][j]);
st[t· ] = true;
}
if (dist[n] == 0x3f3f3f3f) return -1;
return dist[n];
}
2.堆优化版dijkstra
//时间复杂度 O(mlogn), n 表示点数,m 表示边数
typedef pair<int, int> PII;
int n; // 点的数量
int h[N], w[N], e[N], ne[N], idx; // 邻接表存储所有边
int dist[N]; // 存储所有点到1号点的距离
bool st[N]; // 存储每个点的最短距离是否已确定
// 求1号点到n号点的最短距离,如果不存在,则返回-1
int dijkstra()
{
memset(dist, 0x3f, sizeof dist);
dist[1] = 0;
priority_queue<PII, vector, greater> heap;
heap.push({0, 1}); // first存储距离,second存储节点编号
while (heap.size())
{
auto t = heap.top();
heap.pop();
int ver = t.second, distance = t.first;
if (st[ver]) continue;
st[ver] = true;
for (int i = h[ver]; i != -1; i = ne[i])
{
int j = e[i];
if (dist[j] > distance + w[i])
{
dist[j] = distance + w[i];
heap.push({dist[j], j});
}
}
}
if (dist[n] == 0x3f3f3f3f) return -1;
return dist[n];
}
3.Bellman-Ford算法
//时间复杂度 O(nm), n表示点数,m 表示边数
int n, m; // n表示点数,m表示边数
int dist[N]; // dist[x]存储1到x的最短路距离
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
最后
ActiveMQ消息中间件面试专题
- 什么是ActiveMQ?
- ActiveMQ服务器宕机怎么办?
- 丢消息怎么办?
- 持久化消息非常慢怎么办?
- 消息的不均匀消费怎么办?
- 死信队列怎么办?
- ActiveMQ中的消息重发时间间隔和重发次数吗?
ActiveMQ消息中间件面试专题解析拓展:
redis面试专题及答案
- 支持一致性哈希的客户端有哪些?
- Redis与其他key-value存储有什么不同?
- Redis的内存占用情况怎么样?
- 都有哪些办法可以降低Redis的内存使用情况呢?
- 查看Redis使用情况及状态信息用什么命令?
- Redis的内存用完了会发生什么?
- Redis是单线程的,如何提高多核CPU的利用率?
Spring面试专题及答案
- 谈谈你对 Spring 的理解
- Spring 有哪些优点?
- Spring 中的设计模式
- 怎样开启注解装配以及常用注解
- 简单介绍下 Spring bean 的生命周期
Spring面试答案解析拓展
高并发多线程面试专题
- 现在有线程 T1、T2 和 T3。你如何确保 T2 线程在 T1 之后执行,并且 T3 线程在 T2 之后执行?
- Java 中新的 Lock 接口相对于同步代码块(synchronized block)有什么优势?如果让你实现一个高性能缓存,支持并发读取和单一写入,你如何保证数据完整性。
- Java 中 wait 和 sleep 方法有什么区别?
- 如何在 Java 中实现一个阻塞队列?
- 如何在 Java 中编写代码解决生产者消费者问题?
- 写一段死锁代码。你在 Java 中如何解决死锁?
高并发多线程面试解析与拓展
jvm面试专题与解析
- JVM 由哪些部分组成?
- JVM 内存划分?
- Java 的内存模型?
- 引用的分类?
- GC什么时候开始?
JVM面试专题解析与拓展!
- 怎样开启注解装配以及常用注解
- 简单介绍下 Spring bean 的生命周期
Spring面试答案解析拓展
[外链图片转存中…(img-4zsXaOVS-1711865729112)]
高并发多线程面试专题
- 现在有线程 T1、T2 和 T3。你如何确保 T2 线程在 T1 之后执行,并且 T3 线程在 T2 之后执行?
- Java 中新的 Lock 接口相对于同步代码块(synchronized block)有什么优势?如果让你实现一个高性能缓存,支持并发读取和单一写入,你如何保证数据完整性。
- Java 中 wait 和 sleep 方法有什么区别?
- 如何在 Java 中实现一个阻塞队列?
- 如何在 Java 中编写代码解决生产者消费者问题?
- 写一段死锁代码。你在 Java 中如何解决死锁?
高并发多线程面试解析与拓展
[外链图片转存中…(img-1g4lVx8D-1711865729112)]
jvm面试专题与解析
- JVM 由哪些部分组成?
- JVM 内存划分?
- Java 的内存模型?
- 引用的分类?
- GC什么时候开始?
JVM面试专题解析与拓展!
[外链图片转存中…(img-5cjnPspK-1711865729113)]