AcWing3305 -- 建图
1. 题目描述
给定我们一些初始作物,和作物之间杂交的规则(作物 和作物 杂交产生种子 ,花费作物 和作物 成熟时间的最大值),让我们求,某个作物 出现的最小时间
2. 思路
建图
最短路应该是可以看出来的,但是对于给定的规则,作物 和作物 杂交产生种子 ,花费作物 和作物 成熟时间的最大值,我们如何根据这条规则建立边呢?
其实这也没什么好解释的,下面直接告诉你答案:
a -> c,边权为 b
b -> c,边权为 a
值得注意的是,这里的边权并不是传统意义上的边权,它代指一个条件。
到 的边权为 表示: 只有满足拥有 的条件,才能到达(与 杂交产生) 。同理,
到 的边权为 表示, 只有满足拥有 的条件,才能到达(与 杂交产生)。
而真正的边权,就是 max(cost[a], cost[b])
,这里的 cost[a]
就是题目给定的作物 成熟的时间。
所以说,通过本题,你应该明白如下结论:
边不止可以存储边权,还可以存储其他前驱结点以及其他的信息
抽象出问题的模型并建图往往是最难的!
求解
好了,现在我们已经建立了一个图,接下来该如下求解呢?
题目给定了我们一些初始作物,要求我们求目标作物,经典的 N -> 1
问题啊!你应该立马想到,将 N
抽象为 1
(通过虚拟源点),然后就是求单源最短路!
当然,我们也可以不添加虚拟源点,而是模拟虚拟源点的第一趟遍历,将所有初始时给定的作物都加入队列中即可
由于边权都是正值,因此 和 都是可行的。
下面代码中 (1) 的解释
int new_dist = max(distance, dist[w[i]]) + max(cost[ver], cost[w[i]]);
对于这句代码,max(cost[ver], cost[w[i]])
可能还容易理解,因为我们建图的时候就是如此设置的。
但是 max(distance, dist[w[i]])
可能不容易理解了,其实很简单,虽然我们可以通过作物 和 作物 杂交产生作物
但我们也得保证 和 先存在啊,而 和 最晚的那个出现的时间起,我们才可能杂交,否则少一个怎么杂交。。
3. 代码(dijkstra)
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
typedef pair<int, int> PII;
// 添加虚拟源点要多加边数
const int N = 2010, M = 3e5 + 10;
int n, m, k, T;
int cost[N];
int h[N], e[M], ne[M], w[M], idx;
int dist[N];
bool st[N];
void add(int a, int b, int c)
{
w[idx] = c;
e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
}
void dijkstra()
{
priority_queue<PII, vector<PII>, greater<PII>> q;
memset(dist, 0x3f, sizeof dist);
dist[0] = 0;
q.push({0, 0}); // push virtual source node
while(q.size())
{
auto [distance, ver] = q.top(); q.pop();
if(st[ver]) continue;
st[ver] = true;
for(int i = h[ver]; i != -1; i = ne[i])
{
int j = e[i];
int new_dist = max(distance, dist[w[i]]) + max(cost[ver], cost[w[i]]); // (1)
if(new_dist < dist[j])
{
dist[j] = new_dist;
q.push({new_dist, j});
}
}
}
}
int main()
{
memset(h, -1, sizeof h);
cin >> n >> m >> k >> T;
for(int i = 1; i <= n; i ++ ) cin >> cost[i];
// 作物最小编号为0,因为使用0作为虚拟源点
for(int i = 0; i < m; i ++ )
{
int x; cin >> x;
add(0, x, 0); // “边权”也是0
}
for(int i = 0; i < k; i ++ )
{
int a, b, c;
cin >> a >> b >> c;
add(a, c, b);
add(b, c, a);
}
dijkstra();
cout << dist[T] << endl;
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】