• 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;
    }
  • 相关阅读:
    $("*")选取所有的元素
    $("p") 选取多有的元素
    $(".test")选取所有class为test的元素
    $("#test")选取id为test的元素
    数据分析工具的深度对比:FineBI vs PowerBI
    Kafka是如何处理Netflix每天2万亿条消息的?
    新补丁更新(RU和RUR),新的版本(Release 18和19)
    Cinder 的 I/O QoS
    Web前端绘制0.5像素的几种方法
    Web前端绘制0.5像素的几种方法
  • 原文地址:https://www.cnblogs.com/AK-ls/p/10175508.html
Copyright © 2020-2023  润新知