专栏文章

题解:P11860 [CCC 2025 Senior] 熔岩路 / Floor is Lava

P11860题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@mipcpsoi
此快照首次捕获于
2025/12/03 09:51
3 个月前
此快照最后确认于
2025/12/03 09:51
3 个月前
查看原文

P11860 [CCC 2025 Senior] 熔岩路 / Floor is Lava

题目大意

你被困在一个有 nn 个房间和 mm 条双向隧道构成的地牢中。隧道地板上覆盖着温度为 cc 的熔岩,只有当你的耐热靴子冷却等级恰好等于 cc 时,才能安全经过。你从房间 11 出发,初始冷却等级为 00,在房间内可以花费硬币调整冷却等级(每增加或减少 1111 枚金币),目标是以最小金币花费到达房间 nn

解题思路

方案核心在于将问题转化为求一条路径上温度调整的最小成本。对于一条选定的路径,如果依次经过温度 c1,c2,,ckc_1, c_2, …, c_k 的隧道,总花费为 c10+c2c1++ckck1|c_1 − 0| + |c_2 − c_1| + … + |c_k − c_{k-1}|
考虑每个房间内相邻隧道的温度调整问题:
  • 对于同一个房间,把所有出入该房间的隧道按温度排序,任意相邻两隧道间调整的花费即为它们温度之差。
  • 从房间 11 出发,初始冷却等级为 00,因此进入该房间的每条隧道的起始花费为隧道温度。
  • 对于房间 nn,只需保证通过某条隧道到达即可。
因此,我们构造一个以隧道为“节点”的图,
  • 对于每个房间,将该房间中排序后的隧道节点两两建立边,权值为温度差(双向边)。
  • 接着,对于所有出自房间 11 的隧道,初始代价为它们各自的温度;对于所有经过房间 nn 的隧道,记录到达终点的代价。
最后,利用 Dijkstra 在该图上求最短路径,答案即为最低总调整花费。
该方法在构造边时对每个房间按隧道温度排序,所以整体时间复杂度为 O(m×logm)O(m\times \log m)
CPP
#include<bits/stdc++.h>
using  namespace std;

#define ll long long
const ll INF=1e18;

struct edge{
    int u,v,c,id;
};

namespace sunburstfan{
    vector<edge> e;
    vector<vector<int> >raw_e;
    vector<vector<pair<int,ll> > > G;

    bool cmp(int a,int b){
        return e[a-1].c<e[b-1].c;
    }

    ll Dij(int n){
        vector<ll> dis(e.size()+1,INF);
        priority_queue<pair<ll,int>,vector<pair<ll,int> >,greater<pair<ll,int> > > pq;

        for(auto u:raw_e[1]){
            dis[u]=e[u-1].c;
            pq.push({dis[u],u});
        }

        while(!pq.empty()){
            auto p=pq.top(); pq.pop();

            ll u=p.second,c=p.first;
            if(c>dis[u]) continue;

            for(auto v:G[u]){
                if(dis[v.first]>dis[u]+v.second){
                    dis[v.first]=dis[u]+v.second;
                    pq.push({dis[v.first],v.first});
                }
            }

        }

        ll ans=INF;
        for(auto u:raw_e[n]){
            if(dis[u]!=INF){
                ans=min(ans,dis[u]);
            }
        }

        return ans;
    }

}
using namespace sunburstfan;

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);

    int n,m;
    cin>>n>>m;

    if(n==1){
        cout<<0<<"\n";
        return 0;
    }

    raw_e.resize(n+1),G.resize(m+1);
    for(int i=1;i<=m;i++){
        int u,v,c;
        cin>>u>>v>>c;

        e.push_back({u,v,c,i});
        raw_e[u].push_back(i);
        raw_e[v].push_back(i);
    }   

    for(int i=1;i<=n;i++){
        sort(raw_e[i].begin(),raw_e[i].end(),cmp);

        for(int j=1;j<raw_e[i].size();j++){
            int u=raw_e[i][j-1],v=raw_e[i][j];
            ll c=abs(e[v-1].c-e[u-1].c);

            G[u].push_back({v,c});
            G[v].push_back({u,c});
        }
    }
    
    cout<<Dij(n)<<"\n";

    return 0;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...