算法竞赛进阶指南 图论 最短路

341 最优贸易

题意:一张图,由单向边和双向边组成,每个节点有固定的权值,求从1走到n的最大权值之差

(不知道为啥放最短路里,明明一个bfs就可以解决了

存边时除了单向双向边要注意,还要存一张反边图

bfs一遍记录从1到n每个节点到1的最小权值

再bfs一遍跑反边图,记录从n到1每个节点到n的最大权值

最后遍历一遍统计最大差值就ok了

#include<algorithm>
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<string>
#include<map>
#include<queue>
#include<stack>
#include<list>
#include<set>
using namespace std;
typedef long long ll;
typedef pair<ll,ll> P;
typedef long double ld;
#define mem(x) memset(x, 0, sizeof(x))
#define me(x) memset(x, -1, sizeof(x))
#define fi first
#define se second
#define fo(i,n) for(i=0; i<n; i++)
#define sc(x) scanf("%I64d", &x)
#define sca(n,m) scanf("%I64d%I64d", &n, &m)
#define pr(x) printf("%I64d\n", x)
#define pri(x) printf("%I64d ", x)
#define lowbit(x) x&-x
const ll MOD = 1e9 + 7;
const ll oo = 1e18;
const ll N = 4e5 + 5;
struct node
{
    ll nxt, to;
}e[N], e1[N];
ll head[N], cnt, vis[N], mi[N], a[N], vi[N], mx[N];
ll head1[N], cnt1;
void add(ll u, ll v)
{
    e[cnt].to=v;
    e[cnt].nxt=head[u];
    head[u]=cnt++;
}
void add1(ll u, ll v)
{
    e1[cnt1].nxt=head1[u];
    e1[cnt1].to=v;
    head1[u]=cnt1++;
}

void bfs(ll n)
{
    queue<ll> q;
    q.push(1);
    vis[1]=1;
    mi[1]=min(mi[1], a[1]);
    while(q.size())
    {
        ll u=q.front();
        q.pop();
        for(ll i=head[u]; ~i; i=e[i].nxt)
        {
            ll v=e[i].to;
            mi[v]=min(min(mi[v],a[v]), mi[u]);
            if(!vis[v])
            {
                vis[v]=1;
                q.push(v);
            }
        }
    }
    q.push(n);
    vi[n]=1;
    mx[n]=max(mx[n], a[n]);
    while(q.size())
    {
        ll u=q.front();
        q.pop();
        for(ll i=head1[u]; ~i; i=e1[i].nxt)
        {
            ll v=e1[i].to;
            mx[v]=max(max(mx[v],a[v]), mx[u]);
            if(!vi[v])
            {
                vi[v]=1;
                q.push(v);
            }
        }
    }
}
int main()
{
    ll i, j, k;
    ll n, m;
    ll u, v;
    cin>>n>>m;
    for(i=1; i<=n; i++)
        cin>>a[i], mi[i]=oo, head[i]=-1, mx[i]=-oo, head1[i]=-1;
    while(m--)
    {
        cin>>u>>v>>k;
        if(k==1) add(u,v), add1(v,u);
        else add(u,v), add(v,u), add1(u,v), add1(v,u);
    }
    bfs(n);
    ll ans=0;
    for(i=1; i<=n; i++) //cout<<mi[i]<<" "<<mx[i]<<endl;
    {
        if(mi[i]!=oo && mx[i]!=-oo && mx[i]>mi[i])
            ans=max(mx[i]-mi[i], ans);
    }
    cout<<ans<<endl;
    return 0;
}
View Code

 

posted @ 2019-08-03 15:53  op-z  阅读(183)  评论(0编辑  收藏  举报