Luogu P1073 Optimal Trade - Two-way Value

Title: https://www.luogu.org/problemnew/show/P1073

Since any city can be passed through many times, you can walk anywhere, so you don't need to pay too much attention to directed edges and undirected edges, and treat undirected edges as two directed edges;

According to the meaning of the question, the city with lower price must be passed before the city with higher price, but it can walk freely, so it may be considered separately;

Each point maintains two values, one is from the starting point to its minimum value, the other is from the end point to its maximum value, and MAX can be taken from the difference between the two in each city;

So the problem is transformed into finding the shortest path between two single sources. For the one starting from the end point, all the edges can be reversed to perform the shortest path.

code show as below:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
priority_queue< pair<int,int> >q;
int const MAXN=1e5+5,MAXM=5e5+5;
int n,m,head[MAXN],ct,s[MAXN],t[MAXN],head2[MAXN],ct2,cost[MAXN],ans;
bool vis[MAXN];
struct N{
    int to,next;
    N(int t=0,int n=0):to(t),next(n) {}
} edge [MAXM], edge2 [MAXM];
void add(int x,int y,int z)
{
    edge[++ct]=N(y,head[x]);head[x]=ct;
    edge2[++ct2]=N(x,head2[y]);head2[y]=ct;
    if(z==2)
    {
        edge[++ct]=N(x,head[y]);head[y]=ct;
        edge2[++ct2]=N(y,head2[x]);head2[x]=ct;
    }
}
void dijkstra1()
{
    while(q.size())q.pop();
    memset(s,0x3f,sizeof s);
    memset(vis,0,sizeof vis);
    s[1]=cost[1];q.push(make_pair(-cost[1],1));//大根堆 
    while(q.size())
    {
        int x=q.top().second;q.pop();
        if(vis[x])continue;//!
        vis[x]=1;
        for(int i=head[x],u;i;i=edge[i].next)
            if(s[u=edge[i].to]>min(s[x],cost[u]))
            {
                s[u]=min(s[x],cost[u]);
                q.push(make_pair(-s[u],u));
            }
    }
}
void dijkstra2()
{
    while(q.size())q.pop();
    memset(t,-3,sizeof t);
    memset(vis,0,sizeof vis);
    t[n]=cost[n];q.push(make_pair(cost[n],n));//大根堆 
    while(q.size())
    {
        int x=q.top().second;q.pop();
        if(vis[x])continue;//!
        vis[x]=1;
        for(int i=head2[x],u;i;i=edge2[i].next)
            if(t[u=edge2[i].to]<max(t[x],cost[u]))
            {
                t[u]=max(t[x],cost[u]);
                q.push(make_pair(t[u],u));
            }
    }
}
intmain ()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        scanf("%d",&cost[i]);
    for(int i=1,x,y,z;i<=m;i++)
    {
        scanf("%d%d%d",&x,&y,&z);
        add(x,y,z);
    }
    dijkstra1();
    dijkstra2();
    for(int i=1;i<=n;i++)
        ans=max(ans,t[i]-s[i]);
    printf("%d",ans);
    return 0;
}

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324750996&siteId=291194637