P9026 [CCC2021 S4] Daily Commute

原题链接

一步一步来

1.假设D为1,你要怎么求?

每个点乘地铁的时间是唯一的,也就是说,如果我一开始先走一段路到A点再坐地铁,等价于我直接坐地铁到A点,下地铁的瞬间再次上车。
所以最优路径一定可以是先从起点乘地铁到某个点,然后再一直走路到终点

因此我们可以遍历 S 的每个点,求出在该点下车的最短时间
由于求多条最短路,所以我们改变建边的方向,求单源最短路

时间复杂度 O(m+n)

2.由于D的范围很大,我们没法每天遍历一遍S,发现交换只会影响两个点的下车的最短时间
所以我们可以用堆维护所有点下车的最短时间,只有堆顶元素处于它这一天应该在的位置上时有效

code

using namespace std;

vector<int> G[200005];

int dis[200005];
int s[200005];

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


struct unit
{
    int id,pos;
    bool operator<(const unit &b) const
    {
        return b.pos-1+dis[b.id]<pos-1+dis[id];
    }
};
int main()
{

    memset(dis,0x3f,sizeof dis);
    int n,w,d;
    cin>>n>>w>>d;

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

    priority_queue<node> q;
    q.push({n,0});
    while(q.size())
    {
        int now=q.top().pos,val=q.top().val;
        q.pop();
        if(dis[now]<=val) continue;
        dis[now]=val;
        for(auto next:G[now])
        {
            if(dis[next]>dis[now]+1)
            {
                q.push({next,dis[now]+1});
            }
        }
    }



    priority_queue<unit> ans;

    for(int i=1;i<=n;i++)
    {
        cin>>s[i];
        ans.push({s[i],i});
    }

    while(d--)
    {
        int x,y;
        cin>>x>>y;
        swap(s[x],s[y]);

        ans.push({s[x],x});
        ans.push({s[y],y});

        while(s[ans.top().pos]!=ans.top().id) ans.pop();
        cout<<ans.top().pos-1+dis[ans.top().id]<<"\n";
    }
    return 0;
}


posted @   纯粹的  阅读(43)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
点击右上角即可分享
微信分享提示