P1219 最优贸易

C国有 n 个大城市和 m 条道路,每条道路连接这 n 个城市中的某两个城市。

任意两个城市之间最多只有一条道路直接相连。

这 m 条道路中有一部分为单向通行的道路,一部分为双向通行的道路,双向通行的道路在统计条数时也计为1条。

C国幅员辽阔,各地的资源分布情况各不相同,这就导致了同一种商品在不同城市的价格不一定相同。

但是,同一种商品在同一个城市的买入价和卖出价始终是相同的。

商人阿龙来到C国旅游。

当他得知“同一种商品在不同城市的价格可能会不同”这一信息之后,便决定在旅游的同时,利用商品在不同城市中的差价赚一点旅费。

设C国 n 个城市的标号从 1~n,阿龙决定从1号城市出发,并最终在 n 号城市结束自己的旅行。

在旅游的过程中,任何城市可以被重复经过多次,但不要求经过所有 n 个城市。

阿龙通过这样的贸易方式赚取旅费:他会选择一个经过的城市买入他最喜欢的商品——水晶球,并在之后经过的另一个城市卖出这个水晶球,用赚取的差价当做旅费。

因为阿龙主要是来C国旅游,他决定这个贸易只进行最多一次,当然,在赚不到差价的情况下他就无需进行贸易。

现在给出 n 个城市的水晶球价格,m 条道路的信息(每条道路所连接的两个城市的编号以及该条道路的通行情况)。

请你告诉阿龙,他最多能赚取多少旅费。

输入格式

第一行包含 2 个正整数 n 和 m,中间用一个空格隔开,分别表示城市的数目和道路的数目。

第二行 n 个正整数,每两个整数之间用一个空格隔开,按标号顺序分别表示这 n 个城市的商品价格。

接下来 m 行,每行有 3 个正整数,x,y,z,每两个整数之间用一个空格隔开。

如果z=1,表示这条道路是城市 x 到城市 y 之间的单向道路;如果z=2,表示这条道路为城市 x 和城市 y 之间的双向道路。

输出格式

一个整数,表示答案。

数据范围

1n1000001≤n≤100000,
1m5000001≤m≤500000,
1100


AC这道题已经是第二遍了,第一次是用别人一个叫DP的代码水过的,尽管我都不知道什么是DP;今天突然有了灵感,自己又写了一遍,用双向SPFA,第一次就过了,和大家分享一下;

#include <bits/stdc++.h>

using namespace std;

#define N 100000

inline int read()
{
    int x = 0,ff = 1;char ch = getchar();
    while(!isdigit(ch))
    {
        if(ch == '-') ff = -1;
        ch = getchar();
    }
    while(isdigit(ch))
    {
        x = (x<<1) + (x<<3) + (ch ^ 48);
        ch = getchar();
    }
    return x * ff;
}

inline void write(int x)
{
    if(x < 0) putchar('-'),x = -x;
    if(x > 9) write(x / 10);
    putchar(x % 10 + '0');
}

int a,b,ans;
struct node
{
    int y,next;
}e1[N<<1],e2[N<<1];
int tot1,lin1[N<<1];
int tot2,lin2[N<<1];
int mon[N<<1],mi[N<<1],ma[N<<1];
int head,tail,q[N<<1],vis[N<<1];

void add1(int xx,int yy)
{
    e1[++tot1].y = yy;
    e1[tot1].next = lin1[xx];
    lin1[xx] = tot1;
}

void add2(int xx,int yy)
{
    e2[++tot2].y = yy;
    e2[tot2].next = lin2[xx];
    lin2[xx] = tot2;
}

void SPFA1(int s)
{
    memset(vis,false,sizeof(vis));
    memset(mi,0x3f,sizeof(mi));
    head = 1,tail = 1;
    q[1] = s; mi[s] = mon[s];
    for(head = 1;head <= tail;++head)
    {
        int x = q[head];
        vis[x] = false;
        for(int i = lin1[x],y;i;i = e1[i].next)
        {
            if(mi[y = e1[i].y] > mi[x])
            {
                mi[y] = min(mon[y],mi[x]);
                if(!vis[y])
                {
                    vis[y] = true;
                    q[++tail] = y;
                }
            }
        }
    }
}

void SPFA2(int s)
{
    memset(vis,false,sizeof(vis));
    head = 1,tail = 1;
    q[1] = s; ma[s] = mon[s];
    for(head = 1;head <= tail;++head)
    {
        int x = q[head];
        vis[x] = false;
        for(int i = lin2[x],y;i;i = e2[i].next)
        {
            if(ma[y = e2[i].y] < ma[x])
            {
                ma[y] = max(mon[y],ma[x]);
                if(!vis[y])
                {
                    vis[y] = true;
                    q[++tail] = y;
                }
            }
        }
    }
}

int main()
{
    a = read(); b = read();
    for(int i = 1;i <= a;++i)
    mon[i] = read();
    for(int i = 1;i <= b;++i)
    {
        int x,y,z;
        x = read(); y = read(); z = read();
        add1(x,y);
        add2(y,x);
        if(z == 2)
        {
            add1(y,x);
            add2(x,y);
        }
    }
    SPFA1(1); SPFA2(a);
    for(int i = 1;i <= a;++i)
    ans = max(ans,ma[i] - mi[i]);
    write(ans); 
    return 0;
}

下面是第一次的代码,大佬可以参考一下......

#include<bits/stdc++.h>
#define INF 0x7f7f7f7f
#define MAXN 100005
using namespace std;

vector<int> g[MAXN];
int n,m,f[MAXN],mi[MAXN],c[MAXN];

void dfs(int x,int minx,int pre) {
    int flag=1; 
    minx=min(c[x],minx);
    if (mi[x]>minx) mi[x]=minx,flag=0;
    int maxx=max(f[pre],c[x]-minx);
    if (f[x]<maxx) f[x]=maxx,flag=0;
    if (flag) return;
    for (int i=0;i<g[x].size();i++) dfs(g[x][i],minx,x);
}

int main() {
    scanf("%d%d",&n,&m);
    for (int i=0;i<MAXN;i++) mi[i]=INF;
    for (int i=1;i<=n;i++) scanf("%d",&c[i]);
    for (int i=1;i<=m;i++) {
        int t1,t2,t3;
        scanf("%d%d%d",&t1,&t2,&t3);
        g[t1].push_back(t2);
        if (t3==2) g[t2].push_back(t1);
    }
    dfs(1,INF,0);
    printf("%d
",f[n]);
    return 0;
}
原文地址:https://www.cnblogs.com/AK-ls/p/10175508.html