P1073 最优贸易 (tarjan缩点+dp)

题目链接:https://www.luogu.com.cn/problem/P1073。

C国有n n n个大城市和m mm 条道路,每条道路连接这 nnn个城市中的某两个城市。任意两个城市之间最多只有一条道路直接相连。这 mmm 条道路中有一部分为单向通行的道路,一部分为双向通行的道路,双向通行的道路在统计条数时也计为 11 1条。

CC C国幅员辽阔,各地的资源分布情况各不相同,这就导致了同一种商品在不同城市的价格不一定相同。但是,同一种商品在同一个城市的买入价和卖出价始终是相同的。

商人阿龙来到 CCC 国旅游。当他得知同一种商品在不同城市的价格可能会不同这一信息之后,便决定在旅游的同时,利用商品在不同城市中的差价赚回一点旅费。设 CCC 国 n 个城市的标号从 1 n1~ n1 n,阿龙决定从 11 1号城市出发,并最终在 nnn 号城市结束自己的旅行。在旅游的过程中,任何城市可以重复经过多次,但不要求经过所有 nnn 个城市。阿龙通过这样的贸易方式赚取旅费:他会选择一个经过的城市买入他最喜欢的商品――水晶球,并在之后经过的另一个城市卖出这个水晶球,用赚取的差价当做旅费。由于阿龙主要是来 CCC 国旅游,他决定这个贸易只进行最多一次,当然,在赚不到差价的情况下他就无需进行贸易。

方法:

此题好多方法可解。比如2*SPFA, 分层图+SPFA.

此文主要用tarjan+dp.

$minp[v]=min(minp[v],minp[u])$
$dp[v]=max(dp[v],max(dp[u],maxp[v]-minp[v]))$

Code:

#include <bits/stdc++.h>
# define LL long long
using namespace std;

const int maxn=100000+10;
const int maxm=500000+10;
int n,m;
int price[maxn];

struct Edge{
    int to,next;
};
Edge e[maxm<<1];
int head[maxn];
int en;

Edge e1[maxm<<1]; //缩点后新图
int head1[maxn];
int en1;
//tarjan组员
int dict[maxn],low[maxn];
int instack[maxn];
stack<int> stk;
int color;
int col[maxn];
int maxp[maxn];   //一个scc中的最大价值
int minp[maxn];  //一个scc中的最小价值
int timer;
//dp组员
int indegree[maxn];
int dp[maxn];
queue<int> q;

void add(int from, int to){
    e[en].next=head[from];
    e[en].to=to;
    head[from]=en;
    ++en;
}

void add1(int from, int to){
    e1[en1].next=head1[from];
    e1[en1].to=to;
    head1[from]=en1;
    ++en1;
}

void tarjan(int u){
    instack[u]=1;
    stk.push(u);
    ++timer;
    dict[u]=low[u]=timer;
    for(int i=head[u];i!=-1;i=e[i].next){
        int v=e[i].to;
        if(dict[v]==-1){
            tarjan(v);
            low[u]=min(low[u],low[v]);
        }else{
            if(instack[v]){
                low[u]=min(low[u],dict[v]);
            }
        }
    }
    if(low[u]==dict[u]){
        ++color;
        while(stk.top()!=u){
            int t=stk.top();
            stk.pop();
            instack[t]=0;
            col[t]=color;
            maxp[color]=max(maxp[color],price[t]);
            minp[color]=min(minp[color],price[t]);
        }
        stk.pop();
        instack[u]=0;
        col[u]=color;
        maxp[color]=max(maxp[color],price[u]);
        minp[color]=min(minp[color],price[u]);
    }
}

int helper(){
    int start=col[1];
    dp[start]=max(0,maxp[start]-minp[start]);
    q.push(start);
    while(!q.empty()){
        int u=q.front();
        q.pop();
        for(int i=head1[u];i!=-1;i=e1[i].next){
            int v=e1[i].to;
            minp[v]=min(minp[v],minp[u]);
            dp[v]=max(dp[v],max(dp[u],maxp[v]-minp[v]));
            indegree[v]--;
            if(indegree[v]==0){
                q.push(v);
            }
        }
    }
    return dp[col[n]];
}

int main(){
    memset(head,-1,sizeof(head));
    memset(head1,-1,sizeof(head1));
    scanf("%d %d", &n, &m);
    for(int i=1;i<=n;++i){
        scanf("%d", price+i);
    }
    for(int i=1;i<=m;++i){
        int a, b, c;
        scanf("%d %d %d", &a, &b, &c);
        add(a,b);
        if(c==2){
            add(b,a);
        }
    }

    memset(dict,-1,sizeof(dict));
    memset(minp,127,sizeof(minp));
    tarjan(1);

    vector<set<int>> nadj(color+1);
    for(int i=1;i<=n;++i){
        if(dict[i]==-1) continue;  //筛掉从1不可到的点
        for(int j=head[i];j!=-1;j=e[j].next){
            int v=e[j].to;
            if(dict[v]==-1) continue;   //筛掉从1不可到的点
            int nu=col[i];
            int nv=col[v];
            if(nu==nv) continue;
            if(nadj[nu].find(nv)==nadj[nu].end()){
                nadj[nu].insert(nv);
                add1(nu,nv);
                indegree[nv]++;
            }
        }
    }

    int res=helper();
    printf("%d", res);
}

原文地址:https://www.cnblogs.com/FEIIEF/p/12242554.html

时间: 2024-10-10 19:01:37

P1073 最优贸易 (tarjan缩点+dp)的相关文章

[NOIP2009][LuoguP1073] 最优贸易 - Tarjan,拓扑+DP

Description&Data 题面:https://www.luogu.org/problemnew/show/P1073 Solution Tarjan对联通块缩点,在DAG上按照拓扑序更新最低买入价,到每个点时再更新一下答案,即联通块内最大卖出价减去沿途的最低价格,复杂度O(n). 看机房其他人有写双向SPFA,代码短一些,反向建一张图,一遍跑最大一遍跑最小,最后枚举一下最优答案即可 Tarjan代码如下:(SPFA在后面) #include<iostream> #includ

P1073 最优贸易

P1073 最优贸易 题目描述 C 国有 n 个大城市和 m 条道路,每条道路连接这 n 个城市中的某两个城市.任意两个 城市之间最多只有一条道路直接相连.这 m 条道路中有一部分为单向通行的道路,一部分 为双向通行的道路,双向通行的道路在统计条数时也计为 1 条. C 国幅员辽阔,各地的资源分布情况各不相同,这就导致了同一种商品在不同城市的价 格不一定相同.但是,同一种商品在同一个城市的买入价和卖出价始终是相同的. 商人阿龙来到 C 国旅游.当他得知同一种商品在不同城市的价格可能会不同这一信息

[NOIP2009提高组]最优贸易 tarjan题解

今天刚刚学会了用tarjan写缩点(以前用两遍dfs写的),此题调了我很久,需要考虑的情况有些多,但是做出来还是挺开心的. 首先通过tarjan缩点,之后要干的事情就是计算答案. 答案有两种情况,一是在一个联通块中买进卖出,二是在一个联通块中买入,但在另外一个联通块中卖出.但是需要注意的是,以上两种情况中的联通块需要满足起点可以到达它,它也可以到达终点,并且不在一个联通块中时,买进必在卖出前. 代码中的dp(x)记录的是从起点到现在买进价最低的,每次只要用当前最大价钱减去这个值,再去和ans做比

luogu P1073 最优贸易

luogu P1073 最优贸易 2017-09-14 题目描述 C 国有 n 个大城市和 m 条道路,每条道路连接这 n 个城市中的某两个城市.任意两个城市之间最多只有一条道路直接相连.这 m 条道路中有一部分为单向通行的道路,一部分为双向通行的道路,双向通行的道路在统计条数时也计为 1 条. C 国幅员辽阔,各地的资源分布情况各不相同,这就导致了同一种商品在不同城市的价格不一定相同.但是,同一种商品在同一个城市的买入价和卖出价始终是相同的. 商人阿龙来到 C 国旅游.当他得知同一种商品在不同

洛谷P1073 最优贸易==codevs1173 最优贸易

P1073 最优贸易 题目描述 C 国有 n 个大城市和 m 条道路,每条道路连接这 n 个城市中的某两个城市.任意两个 城市之间最多只有一条道路直接相连.这 m 条道路中有一部分为单向通行的道路,一部分 为双向通行的道路,双向通行的道路在统计条数时也计为 1 条. C 国幅员辽阔,各地的资源分布情况各不相同,这就导致了同一种商品在不同城市的价 格不一定相同.但是,同一种商品在同一个城市的买入价和卖出价始终是相同的. 商人阿龙来到 C 国旅游.当他得知同一种商品在不同城市的价格可能会不同这一信息

P1073 最优贸易 建立分层图 + spfa

P1073 最优贸易:https://www.luogu.org/problemnew/show/P1073 题意: 有n个城市,每个城市对A商品有不同的定价,问从1号城市走到n号城市可以最多赚多少差价.(旅游为主,赚钱为辅,所以买入和卖出只进行一次. 思路: 建一个有三层的图,三层都是相同的普通的城市路线,第一层向第二层连从第i个城市买入商品的花费,第二层向第三层连从第i个城市卖出商品的所得.从1 向 第一层的终点 ,向第三层的终点跑一遍最大路就行了. #include <algorithm>

【Codeforces】894E.Ralph and Mushrooms Tarjan缩点+DP

题意 给定$n$个点$m$条边有向图及边权$w$,第$i$次经过一条边边权为$w-1-2.-..-i$,$w\ge 0$给定起点$s$问从起点出发最多能够得到权和,某条边可重复经过 有向图能够重复经过的边当且仅当成环,所以tarjan缩点成DAG,缩点后每个点内的权值可以通过二分算出,假设最大的$n$使得$w-\frac{n(n+1)}{2}\ge 0$,那么该点值为$(n+1)w-\frac{n(n+1)(n+2)}{6}$,通过对DAG进行dp算出最长路就是答案 代码 #include <b

NOIP2009最优贸易[spfa变形|tarjan 缩点 DP]

题目描述 C 国有 n 个大城市和 m 条道路,每条道路连接这 n 个城市中的某两个城市.任意两个 城市之间最多只有一条道路直接相连.这 m 条道路中有一部分为单向通行的道路,一部分 为双向通行的道路,双向通行的道路在统计条数时也计为 1 条. C 国幅员辽阔,各地的资源分布情况各不相同,这就导致了同一种商品在不同城市的价 格不一定相同.但是,同一种商品在同一个城市的买入价和卖出价始终是相同的. 商人阿龙来到 C 国旅游.当他得知同一种商品在不同城市的价格可能会不同这一信息 之后,便决定在旅游的

[NOIP2009] 提高组 洛谷P1073 最优贸易

题目描述 C 国有 n 个大城市和 m 条道路,每条道路连接这 n 个城市中的某两个城市.任意两个 城市之间最多只有一条道路直接相连.这 m 条道路中有一部分为单向通行的道路,一部分 为双向通行的道路,双向通行的道路在统计条数时也计为 1 条. C 国幅员辽阔,各地的资源分布情况各不相同,这就导致了同一种商品在不同城市的价 格不一定相同.但是,同一种商品在同一个城市的买入价和卖出价始终是相同的. 商人阿龙来到 C 国旅游.当他得知同一种商品在不同城市的价格可能会不同这一信息 之后,便决定在旅游的