CF938D Buy a Ticket

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

虚拟源点+最短路
首先因为所要求的权值由往返的路费和目的地需要的票价两部分构成,所以我们先对每座城市之间的道路建边,边权直接设为输入的两倍。之后我们建立一个虚拟源点,对所有城市链接一条单向边,边权就是城市的票价,即把点权转换为边权,然后再跑一遍最短路,最后输出这个虚拟源点到达当前遍历的城市的最短路。

因为从虚拟源点到目的地城市一定存在唯一的一条最短路,然而用虚拟源点等效建了一张图之后所有的信息都已经维护在最短路上了。


#define maxn 600010
int a[maxn];
vector<pr> vec[maxn];
int dis[maxn];
int n,m;
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin>>n>>m;
    for(int i=1;i<=m;i++)
    {
        int u,v,w;
        cin>>u>>v>>w;
        vec[u].push_back({v,2*w});
        vec[v].push_back({u,2*w});
    }
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
        vec[0].push_back({i,a[i]});
    }
    memset(dis,0x3f,sizeof(dis));
    priority_queue<PII,vector<PII>,greater<PII> > que;
    vector<int> vis(n+1,0);
    dis[0]=0;
    que.push({dis[0],0});
    while(!que.empty())
    {
        auto x=que.top().second;
        que.pop();
        if(vis[x]) continue;
        vis[x]=1;
        for(auto v:vec[x])
        {
            int to=v[0];
            int w=v[1];
            if(dis[to]>dis[x]+w)
            {
                dis[to]=dis[x]+w;
                que.push({dis[to],to});
            }
        }
    }
    for(int i=1;i<=n;i++)
    {
        cout<<dis[i]<<" ";
    }
}
posted @ 2024-05-14 08:30  Captainfly19  阅读(5)  评论(1编辑  收藏  举报