1 条题解
-
0
自动搬运
来自洛谷,原作者为

封禁用户
None搬运于
2025-08-24 21:44:06,当前版本为作者最后更新于2020-03-02 14:43:00,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
关于Floyd,它太慢了关于spfa,它死了关于dijkstra,还是用它吧
步入正题:
这道题,千万不要被题面所误导
题目大意:点u到点1的最短路+点1到点v的最短路
但是,您要是照着这个思路写代码的话,只能拿到50分,T了5个点
显然,这个做法不够优秀
进一步,我们发现,在第i头奶牛的行动中,肯定会经过1号点
所以,只要跑一边dijkstra就好了,把起点设为1
每当进行一次询问,就输出d[u]+d[v] (d[]记录最短距离)
//注释都在代码里了
上代码:(vector存图+dijkstra+堆优化)
//代码重在实用,不在华丽的操作 #include<cstdio> #include<queue> #include<algorithm> #include<vector> using namespace std; int n,m,t,d[50010],ans; //n个节点,m条边,t次询问,d[]存最短距离,ans为每次询问的答案 struct edge { int to,cost; }; vector<edge>G[50010];//vector存图 typedef pair<int,int>P;//定义一个pair类型的P(只是为了写起来简单一点) void dijkstra(int s)//s为起点,在这道题里就是1 { priority_queue<P,vector<P>,greater<P> >q; //一个P类型(pair)类型的优先队列 for(int i=1;i<=n;i++) d[i]=1e9;//赋初值1e9 d[s]=0;//自己到自己的距离是0 q.push(P{0,s});//加入队列等待处理 while(!q.empty()) { P p=q.top();//取队首 q.pop(); //声明一下:p.first代表的是一个距离,而p.second代表的是一个点, //Tell一个不为人知的秘密, //若把p.first设为一个点,而把p.second设为一个距离, //程序的速度就没有第一个优秀(亲测) int v=p.second;//也是为了写起来简便一点, if(d[v]<p.first) continue;//如果已经是一个最短距离了,continue; for(int i=0;i<G[v].size();i++)//循环点v连接的所有点 { edge e=G[v][i]; if(d[e.to]>d[v]+e.cost)//松弛操作,贪心思想 { d[e.to]=d[v]+e.cost;//更新d[e.to]的值 q.push(P{d[e.to],e.to});//重新加入到队列等待处理 } } } } int main() { scanf("%d%d%d",&n,&m,&t); while(m--) { int u,v,w; scanf("%d%d%d",&u,&v,&w); G[u].push_back(edge{v,w});//注意,这个图是一个无向图 G[v].push_back(edge{u,w}); } dijkstra(1); //以1号点为起点进行dijkstra(),便可获得1号点到其它任意一点的最短距离 while(t--) { ans=0; int u,v; scanf("%d%d",&u,&v); ans=d[u]+d[v];//直接输出答案 printf("%d\n",ans); } return 0;//养成良好习惯 }这世界上不缺少什么水题,而是缺少发现水题的眼睛
看我写的这么认真,是否可以点个赞再走呢?
- 1
信息
- ID
- 2049
- 时间
- 1000ms
- 内存
- 125MiB
- 难度
- 3
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者