题解 P1073 【最优贸易】

· · 题解

需要注意的是就算之前已经走过这个节点也需要再比较是否需要更新因为可能会有双向边

PS:蒟蒻的代码 写的很啰嗦

#include <bits/stdc++.h>

using namespace std;
const int maxn=100000+5;
const int maxm=500000+5;

struct e{
    int to;
    int next;
}edge1[maxm],edge2[maxm];
int head1[maxn],edge_len1=0; //正向图
int head2[maxn],edge_len2=0; //反向图
int w[maxn];
int n,m;
int minx[maxn],maxx[maxn]; //当前节点可以到达的最小值和最大值

void edge_add1(int u,int v) //正向建图
{
    edge1[++edge_len1].to=v;
    edge1[edge_len1].next=head1[u];
    head1[u]=edge_len1;
}
void edge_add2(int u,int v) //反向建图
{
    edge2[++edge_len2].to=v;
    edge2[edge_len2].next=head2[u];
    head2[u]=edge_len2;
}
int m_max(int a,int b,int c)
{
    if(a>b && a>c) return a;
    if(b>a && b>c) return b;
    return c;
}
int m_min(int a,int b,int c)
{
    if(a<b && a<c) return a;
    if(b<a && b<c) return b;
    return c;
}
bool visit[maxn];
void bfs1() //正向BFS找一条路径上的最小值
{
    memset(minx,0x7f7f,sizeof(minx));
    queue<int> q;
    q.push(1);
    minx[1]=w[1];
    while(!q.empty())
    {
        int node=q.front();q.pop();
        for(int i=head1[node];i;i=edge1[i].next)
        {
            int now=edge1[i].to;
            minx[now]=m_min(minx[node],w[now],minx[now]);
            if(!visit[now])
            {
                q.push(now);
                visit[now]=true;
            }
        }
    }
}
void bfs2() //反向BFS找一条路径的最大值
{
    memset(visit,false,sizeof(visit));
    queue<int> q;
    q.push(n);
    maxx[n]=w[n];
    while(!q.empty())
    {
        int node=q.front();q.pop();
        for(int i=head2[node];i;i=edge2[i].next)
        {
            int now=edge2[i].to;
            maxx[now]=m_max(maxx[node],maxx[now],w[now]);
            if(!visit[now])
            {
                q.push(now);
                visit[now]=true;
            }
        }
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        scanf("%d",&w[i]);
    int x,y,z;
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d%d",&x,&y,&z);
        if(z==1)
        {
            edge_add1(x,y); //正反建图
            edge_add2(y,x);
        }
        if(z==2)
        {
            edge_add1(x,y);
            edge_add1(y,x);
            edge_add2(x,y);
            edge_add2(y,x);
        }
    }
    bfs1();
    bfs2();
    int ans=0;
    for(int i=1;i<=n;i++) //枚举每一个点找节点的最大值与最小值差的最大值
    {
        ans=max(ans,maxx[i]-minx[i]);
    }
    printf("%d\n",ans);
    return 0;
}