洛谷 P2984 [USACO10FEB] Chocolate Giving S

文章目录



USACO10FEB Chocolate Giving S

题面翻译

题目链接:https://www.luogu.com.cn/problem/P2984

题目描述

FJ 有 B B B 头奶牛 ( 1 ≤ B ≤ 25000 ) (1\le B\le 25000) (1≤B≤25000),有 N ( 2 × B ≤ N ≤ 50000 ) N(2\times B\le N\le 50000) N(2×B≤N≤50000) 个农场,编号 1 1 1 到 N N N,有 M ( N − 1 ≤ M ≤ 100000 ) M(N-1\le M\le 100000) M(N−1≤M≤100000) 条双向边,第 i i i 条边连接农场 R i R_i Ri 和 S i ( 1 ≤ R i ≤ N , 1 ≤ S i ≤ N ) S_i(1\le R_i\le N, 1\le S_i\le N) Si(1≤Ri≤N,1≤Si≤N),该边的长度是 L i ( 1 ≤ L i ≤ 2000 ) L_i(1\le L_i\le 2000) Li(1≤Li≤2000)。居住在农场 P i P_i Pi 的奶牛 A ( 1 ≤ P i ≤ N ) (1\le P_i\le N) (1≤Pi≤N),想送一份新年礼物给居住在农场 Q i ( 1 ≤ Q i ≤ N ) Q_i(1\le Q_i\le N) Qi(1≤Qi≤N) 的奶牛 B,但是奶牛 A 必须先到 FJ(居住在编号 1 1 1 的农场)那里取礼物,然后再送给奶牛 B。你的任务是:奶牛 A 至少需要走多远的路程?

输入格式

  • 第一行三个整数 N , M , B N,M,B N,M,B。

  • 第 2 2 2 至 M + 1 M+1 M+1 行,每行 3 3 3 个整数 R i , S i , L i R_i,S_i,L_i Ri,Si,Li。

  • 第 M + 2 M+2 M+2 至 M + B + 1 M+B+1 M+B+1 行,进行 B B B 次询问,每行 2 2 2 个整数 P i , Q i P_i ,Q_i Pi,Qi。

输出格式

每次询问输出一个整数,即答案。

题目描述

Farmer John is distributing chocolates at the barn for Valentine's day, and B (1 <= B <= 25,000) of his bulls have a special cow in mind to receive a chocolate gift.

Each of the bulls and cows is grazing alone in one of the farm's N (2*B <= N <= 50,000) pastures conveniently numbered 1...N and connected by M (N-1 <= M <= 100,000) bidirectional cowpaths of various lengths. Some pastures might be directly connected by more than one cowpath. Cowpath i connects pastures R_i and S_i (1 <= R_i <= N; 1 <= S_i <= N) and has length L_i (1 <= L_i <= 2,000).

Bull i resides in pasture P_i (1 <= P_i <= N) and wishes to give a chocolate to the cow in pasture Q_i (1 <= Q_i <= N).

Help the bulls find the shortest path from their current pasture to the barn (which is located at pasture 1) and then onward to the pasture where their special cow is grazing. The barn connects, one way or another (potentially via other cowpaths and pastures) to every pasture.

As an example, consider a farm with 6 pastures, 6 paths, and 3 bulls (in pastures 2, 3, and 5) who wish to bestow chocolates on their love-objects:

cpp 复制代码
                      *1  <-- Bull wants chocolates for pasture 1 cow
             [4]--3--[5]  <-- [5] is the pasture ID
            /  |
           /   |
          4    2          <-- 2 is the cowpath length
         /     |               between [3] and [4]
      [1]--1--[3]*6
     /   \    /
    9     3  2
   /       \/
 [6]      [2]*4

* The Bull in pasture 2 can travel distance 3 (two different ways) to get to the barn then travel distance 2+1 to pastures 3 and 4 to gift his chocolate. That's 6 altogether.

* The Bull in pasture 5 can travel to pasture 4 (distance 3), then pastures 3 and 1 (total: 3 + 2 + 1 = 6) to bestow his chocolate offer.

* The Bull in pasture 3 can travel distance 1 to pasture 1 and then take his chocolate 9 more to pasture 6, a total distance of 10.

输入格式

* Line 1: Three space separated integers: N, M, and B

* Lines 2...M+1: Line i+1 describes cowpath i with three

space-separated integers: R_i, S_i, and L_i

* Lines M+2...M+B+1: Line M+i+1 contains two space separated integers: P_i and Q_i

输出格式

* Lines 1...B: Line i should contain a single integer, the smallest distance that the bull in pasture P_i must travel to get chocolates from the barn and then award them to the cow of his dreams in pasture Q_i

样例 #1

样例输入 #1

复制代码
6 7 3 
1 2 3 
5 4 3 
3 1 1 
6 1 9 
3 4 2 
1 4 4 
3 2 2 
2 4 
5 1 
3 6

样例输出 #1

复制代码
6 
6 
10


题意解析

  • 找一个点先到 1 1 1 号点的最短距离,再找 1 1 1 号点到另一点的最短距离,求两者之和。
  • 乍一看以为是 F l o y d Floyd Floyd 算法,但是一看数据范围很大,那就并不是了,那还有什么算法能解决这种最短路问题呢?
  • 其实这并不是多源最短路问题,因为是双向图,所以你到我的最短路其实也是我到你的最短路,所以这题就变成了 1 1 1 号点到另外两个点的最短路之和的问题了,其实是单源最短路问题。
  • 考虑到 D i j k s t r a Dijkstra Dijkstra 可能超时,所以用 S P F A SPFA SPFA

CODE

cpp 复制代码
#include <iostream>
#include <vector>
#include <cstring>
#include <algorithm>
#include <queue>
#define ll long long
#define INF 0x3f3f3f3f 

using namespace std;

typedef pair<int, int> pii;

const int N = 50050, M = 2e5 + 10;
int h[N], e[M], ne[M], w[M], idx; // 定义图的存储结构
int dist[N]; // 存储每个节点到源点的最短距离
bool st[N]; // 存储每个节点是否在队列中
int n, m, b; // n是节点数,m是边的数目,b是查询的数目

// 添加一条边
void add(int a, int b, int c){
    e[idx] = b; // 边的终点
    ne[idx] = h[a]; // 下一条相同起点的边
    w[idx] = c; // 边的权重
    h[a] = idx++; // 更新起点a的最后一条边
}

// SPFA算法,用于求解单源最短路径
void spfa(){
    memset(dist, INF, sizeof dist); // 初始化所有节点到源点的距离为无穷大
    dist[1] = 0; // 源点到自己的距离为0
    
    queue<int> q;
    q.push(1); // 将源点加入队列
    st[1] = true; // 标记源点已经在队列中
    
    while(q.size()){
        auto t = q.front(); // 取出队首元素
        q.pop();
        st[t] = false; // 标记t已经不在队列中
        
        for(int i = h[t]; i != -1; i = ne[i]){ // 遍历所有从t出发的边
            int j = e[i];
            
            if(dist[j] > dist[t] + w[i]){ // 如果可以通过t到j的距离小于当前的最短距离
                dist[j] = dist[t] + w[i]; // 更新最短距离
                
                if(!st[j]){ // 如果j不在队列中
                    q.push(j); // 将j加入队列
                    st[j] = true; // 标记j已经在队列中
                }
            }
        }
    }
}

int main()
{
    memset(h, -1, sizeof h); // 初始化邻接表
    
    cin >> n >> m >> b; // 输入节点数,边的数目,查询的数目
    while(m--){
        int a, b, c;
        scanf("%d%d%d", &a, &b, &c); // 输入边的信息
        add(a, b, c), add(b, a, c); // 将边添加到图中
    }
    
    spfa(); // 执行SPFA算法,求解最短路径
    
    while(b--){
        int p, q;
        scanf("%d%d", &p, &q); // 输入查询
        
        cout << dist[p] + dist[q] << endl; // 输出结果
    }    
}

给点思考

  • 为什么边权数组不用初始化为 I N F INF INF:
    • 因为只有在遍历队列首元素t的所有出边时才会用到w[i],所以能用到肯定存在,所以不需要初始化。
  • 无向图该注意的问题:
    • 边数应该开两倍,因为无向,开少了就RE
相关推荐
霸道流氓气质3 分钟前
SpringBoot中实现告警判定算法-位报警与模拟量阈值-技术详解
spring boot·算法·jquery
十月的皮皮5 分钟前
STM32从零到量产开发:四路继电器工业控制模块开发实战笔记(小白视角)
c语言·笔记·stm32·stm32cubemx·hal库
行者全栈架构师5 分钟前
混元 Hy3 Agent 实战:季度报告 3 小时变 40 分钟
算法·架构·代码规范
疯狂打码的少年10 分钟前
【软件工程】软件项目管理(人员/产品/过程/项目)
笔记·软件工程
兰令水27 分钟前
hot100【acm版】【2026.7.21打卡-java版本】
java·开发语言·算法·leetcode·面试
qz5zwangzihan135 分钟前
题解:Atcoder Beginner Contest abc467 F - Email Scheduling Optimization
c++·贪心·atcoder·平衡树·abc467·abc467_f·fhq-treap
zyplayer-doc36 分钟前
研发接口文档怎么长期维护:zyplayer-doc把API、Markdown和变更记录放进同一个知识库
大数据·数据库·人工智能·笔记·pdf·ocr
2CM_Embed39 分钟前
F28379D 下载后 VOFA+ 无数据、Reset 后恢复:一次 TZ 中断误触发排查记录
笔记·单片机·sci·c2000·f28379d·vofa·tz
好好沉淀1 小时前
主键选择(自增 vs UUID vs 雪花算法)
java·算法
郝学胜-神的一滴1 小时前
中级OpenGL教程 023:Assimp模型加载全解——从源码到架构的骈文探秘
c++·unity·游戏引擎·cmake·unreal engine·opengl