LUOGU P1073 最优贸易

传送门

解题思路

首先可以将无向图视作有向图,然后建立一个反图,之后正着跑一遍最短路存到dis里,dis[x]表示1-x的路径中权值最小节点的权值,反着跑一遍最长路,dis_[x]表示x-n中权值最大的节点的权值,之后用dis_[x]-dis[x]来更新答案。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>

using namespace std;
const int MAXN = 100005,MAXM = 500005;

struct Edge{
    int nxt,to;
}edge[MAXM],edge_s[MAXM];

int head_s[MAXN],cnt_s,dis_s[MAXN],ans;
int n,m,cnt,head[MAXN],dis[MAXN],val[MAXN];
bool vis[MAXN],vis_s[MAXN];
queue<int> q,Q;

inline void add(int bg,int ed){
    edge[++cnt].to=ed;
    edge[cnt].nxt=head[bg];
    head[bg]=cnt;
}

inline void add_s(int bg,int ed){
    edge_s[++cnt_s].to=ed;
    edge_s[cnt_s].nxt=head_s[bg];
    head_s[bg]=cnt_s;
}

inline void spfa(){
    memset(dis,0x3f,sizeof(dis));
    vis[1]=1;q.push(1);dis[1]=val[1];
    while(!q.empty()){
        int x=q.front();q.pop();
        vis[x]=0;
        for(int i=head[x];i;i=edge[i].nxt){
            int u=edge[i].to;
            if(dis[u]>min(val[u],dis[x])){
                dis[u]=min(val[u],dis[x]);
                if(!vis[u]){
                    vis[u]=1;
                    q.push(u);
                }
            }
        }
    }
//  for(register int i=1;i<=n;i++)
//      cout<<dis[i]<<endl;
}

inline void spfa_s(){
    memset(dis_s,-1,sizeof(dis_s));
    vis_s[n]=1;
    dis_s[n]=val[n];
    Q.push(n);
    while(!Q.empty()){
        int x=Q.front();Q.pop();
        vis_s[x]=1;
        for(int i=head_s[x];i;i=edge_s[i].nxt){
            int u=edge_s[i].to;
            if(dis_s[u]<max(dis_s[x],val[u])){
                dis_s[u]=max(dis_s[x],val[u]);
                if(!vis_s[u]){
                    vis_s[u]=1;
                    Q.push(u);
                }
            }
        }
    }
//  for(register int i=1;i<=n;i++)  
//      cout<<dis_s[i]<<endl;
}

int main(){
    scanf("%d%d",&n,&m);
    for(register int i=1;i<=n;i++)  scanf("%d",&val[i]);
    for(register int i=1;i<=m;i++){
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        if(z==1){
            add(x,y);
            add_s(y,x);
        }
        else{
            add(x,y);add(y,x);
            add_s(x,y);add_s(y,x);
        }
    }spfa();spfa_s();
    for(register int i=1;i<=n;i++)
        ans=max(dis_s[i]-dis[i],ans);
    printf("%d",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/sdfzsyq/p/9676969.html