P9650 [SNCPC2019] Escape Plan

原题链接

开始

敲代码前问问自己:如何证明你的算法的正确性?

启发

我们一开始在节点1,假如有abcd四条边,且我们已知 从每条边出发到达终点的最短距离 a<b<c<dd[1]=3
请问我们要封 节点1 的哪条边?
答案显然是abc

那么好接下来我们走边d,假设到达了节点3,我们把节点3当成节点1,又回到了上述情景

一句话总结

我们要率先封住那些 使得当前节点到终点距离最小的边

code

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll maxs=2e18;
int e[100005];
int d[100005];
ll dis[100005];
struct node
{
    int to,len;
};
vector<node> G[100005];

struct fresh
{
    int pos,val;
    bool operator<(const fresh &b) const
    {
        return b.val<val;
    }
};

void solve()
{
    int n,m,k;
    cin>>n>>m>>k;

    for(int i=1;i<=k;i++) cin>>e[i];

    for(int i=1;i<=n;i++)
    {
        cin>>d[i];
        dis[i]=maxs;
    }

    for(int i=1;i<=m;i++)
    {
        int x,y,w;
        cin>>x>>y>>w;
        G[x].push_back({y,w});
        G[y].push_back({x,w});
    }

    priority_queue<fresh> q;
    for(int i=1;i<=k;i++)
    {
        q.push({e[i],0});
        d[e[i]]=0;
    }

    while(q.size())
    {
        int now=q.top().pos,val=q.top().val;
        q.pop();

        if(dis[now]<=val) continue;
        if(d[now])
        {
            d[now]--;
            continue;
        }
        dis[now]=val;
        for(auto next:G[now])
        {
            int to=next.to,len=next.len;
            if(dis[now]+len<dis[to])
            {
                q.push({to,len+dis[now]});
            }
        }
    }

    if(dis[1]!=maxs) cout<<dis[1]<<"\n";
    else cout<<"-1\n";

    for(int i=1;i<=n;i++)
    {
        G[i].clear();
    }
}
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        solve();
    }
    return 0;
}

posted @   纯粹的  阅读(25)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
点击右上角即可分享
微信分享提示