Description&Data

题面:https://www.luogu.org/problemnew/show/P1073

Solution

Tarjan对联通块缩点,在DAG上按照拓扑序更新最低买入价,到每个点时再更新一下答案,即联通块内最大卖出价减去沿途的最低价格,复杂度O(n).

看机房其他人有写双向SPFA,代码短一些,反向建一张图,一遍跑最大价格,一遍跑最小价格,这样保证最大差值产生自同一条路径,最后取差即为答案。

Tarjan代码如下:(SPFA在后面)

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<cctype>
#include<algorithm>
#include<stack>
#define maxn 100005
#define maxm 500005
using namespace std;
struct edge{
    int to,nxt;
}e[maxm<<1],ce[maxm];
int edgenum,lnk[maxn],a[maxn],n,m,u,v,t;
int dfn[maxn],low[maxn],blk[maxn],dgr[maxn],cnt,num;
int mn[maxn],mx[maxn],f[maxn],q[maxn],hd=0,tl=1;
int ans[maxn];
bool vis[maxn];
stack<int> st;
inline int rd()
{
    int x=0;char c=getchar();
    while(!isdigit(c))c=getchar();
    while(isdigit(c))x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return x;
}
void add(int bgn,int end)
{
    e[++edgenum].to=end;
    e[edgenum].nxt=lnk[bgn];
    lnk[bgn]=edgenum;
}
int cedgenum,clnk[maxn];
void c_add(int bgn,int end)
{
    ce[++cedgenum].to=end;
    ce[cedgenum].nxt=clnk[bgn];
    clnk[bgn]=cedgenum;
}
void tarjan(int x)
{
    dfn[x]=low[x]=++cnt;
    vis[x]=1;
    st.push(x);
    for(int p=lnk[x];p;p=e[p].nxt){
        int y=e[p].to;
        if(!dfn[y]){
            tarjan(y);
            low[x]=min(low[x],low[y]);
        }
        else if(vis[y])low[x]=min(low[x],dfn[y]);
    }
    if(low[x]==dfn[x]){
        int now;
        num++;
        do{
            now=st.top();st.pop();
            mn[num]=min(mn[num],a[now]);
            mx[num]=max(mx[num],a[now]);
            vis[now]=0;
            blk[now]=num;
        }while(now!=x);
    }
}
void topo()
{
    for(int i=1;i<=num;++i){
        f[i]=mn[i];
        if(!dgr[i])q[tl++]=i;
    }

    while(++hd<tl){
        int u=q[hd];
        for(int p=clnk[u];p;p=ce[p].nxt){
            int y=ce[p].to;
            if(!--dgr[y])q[tl++]=y;
        }
    }
}
void solve()
{
    hd=0;
    while(++hd<tl){
        int u=q[hd];
        ans[u]=max(ans[u],mx[u]-f[u]);
        for(int p=clnk[u];p;p=ce[p].nxt){
            int y=ce[p].to;
            f[y]=min(f[y],f[u]);
            ans[y]=max(ans[y],ans[u]);
        }
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;++i)
        mn[i]=0x3f3f3f;
    for(int i=1;i<=n;++i)a[i]=rd();
    for(int i=1;i<=m;++i){
        u=rd(),v=rd(),t=rd();
        if(t==1)add(u,v);
        else add(u,v),add(v,u);
    }
    for(int i=1;i<=n;++i)
        if(!dfn[i])tarjan(i);
    int s=blk[1],end=blk[n];
    for(int i=1;i<=n;++i){
        for(int p=lnk[i];p;p=e[p].nxt){
            int y=e[p].to;
            if(blk[i]!=blk[y])c_add(blk[i],blk[y]),dgr[blk[y]]++;
        }
    }
    topo();
    solve();
    printf("%d\n",ans[end]);
    return 0;
} 

SPFA占坑

[NOIP2009][LuoguP1073] 最优贸易 - Tarjan,拓扑+DP的更多相关文章

  1. 「NOIP2009」最优贸易 题解

    「NOIP2009」最优贸易 题解 题目TP门 题目描述 \(C\)国有\(n\)个大城市和\(m\)条道路,每条道路连接这\(n\)个城市中的某两个城市.任意两个城市之间最多只有一条道路直接相连.这 ...

  2. 「NOIP2009」最优贸易

    「NOIP2009」最优贸易 「NOIP2009」最优贸易内存限制:128 MiB时间限制:1000 ms 题目描述C 国有 n 个大城市和 m 条道路,每条道路连接这 n 个城市中的某两个城市.任意 ...

  3. 洛谷P1073 最优贸易 [图论,DP]

    题目传送门 最优贸易 题目描述 C 国有n 个大城市和m 条道路,每条道路连接这n 个城市中的某两个城市.任意两个城市之间最多只有一条道路直接相连.这m 条道路中有一部分为单向通行的道路,一部分为双向 ...

  4. luogu1073 最优贸易 (tarjan+dp)

    tarjan缩点,然后按照拓扑序,做1号点能到达的点的答案具体做法是对每个点记一个min[i],max[i],vis[i]和ans[i]做拓扑序的时候,假设在从u点开始做,有边u到v,如果vis[u] ...

  5. [模板][Luogu3387] 缩点 - Tarjan, 拓扑+DP

    Description 给定一个n个点m条边有向图,每个点有一个权值,求一条路径,使路径经过的点权值之和最大.你只需要求出这个权值和. 允许多次经过一条边或者一个点,但是,重复经过的点,权值只计算一次 ...

  6. NOIP2009 t3 最优贸易

    题目传送门:洛谷P1073 dalao们都用的tarjan啊拓扑排序啊之类的玩意儿,我这个蒟蒻不会,只想到了极其暴力的分层图最短路 设三个状态 0表示没有发生任何买卖的情况 1表示买了没有卖的情况 2 ...

  7. bzoj 2208: [Jsoi2010]连通数【tarjan+拓扑+dp】

    我总觉得枚举点bfs也行-- tarjan缩点,记一下每个scc的size,bitset压一下scc里的点,然后按拓扑倒序向上合并到达状态,然后加ans的时候记得乘size #include<i ...

  8. 【NOIP2009】最优贸易

    描述 C 国有 n 个大城市和 m 条道路,每条道路连接这 n 个城市中的某两个城市.任意两个城市之间最多只有一条道路直接相连.这 m 条道路中有一部分为单向通行的道路,一部分为双向通行的道路,双向通 ...

  9. #2590. 「NOIP2009」最优贸易

    C 国有 n 个大城市和 m 条道路,每条道路连接这 n 个城市中的某两个城市.任意两个城市之间最多只有一条道路直接相连.这 m 条道路中有一部分为单向通行的道路,一部分为双向通行的道路,双向通行的道 ...

随机推荐

  1. Mysql自连接的一些用法

    自连接是连接的一种用法,但并不是连接的一种类型,因为他的本质是把一张表当成两张表来使用. mysql有时在信息查询时需要进行对自身连接(自连接),所以我们需要为表定义别名. 我们举例说明,下面是商品采 ...

  2. MYSQL数据库学习十 单表数据记录查询

    10.1 简单数据记录查询 SELECT field1,field2,...fieldn FROM table_name; “*” ——查询所有记录 SELECT * FROM table_name; ...

  3. 插入排序—直接插入排序(Straight Insertion Sort)

    基本思想: 将一个记录插入到已排序好的有序表中,从而得到一个新,记录数增1的有序表.即:先将序列的第1个记录看成是一个有序的子序列,然后从第2个记录逐个进行插插入到已入,直至整个序列有序为止. 要点: ...

  4. PAT-L3-球队“食物链”-dfs-状压-set

    题目分析: 1. 一场双循环赛制的篮球赛,注意双循环,双循环! 2. 共有n只球队,两两之间有胜有负有平局: 3. 输入: 举例: 第一行:W:代表球队1打赢过这只队伍 L:代表球队2没打赢过这只队伍 ...

  5. Spring Cloud Consul 实现服务注册和发现

    Spring Cloud 是一个基于 Spring Boot 实现的云应用开发工具,它为基于 JVM 的云应用开发中涉及的配置管理.服务发现.断路器.智能路由.微代理.控制总线.全局锁.决策竞选.分布 ...

  6. Loadrunner初学

    1.创建脚本 启动Vvitrual User Generator 创建脚本 因为我们选择录制页面相关的操作,则选择web(HTTP/HTML) application type 选择是录制浏览器网页还 ...

  7. 微信公众平台开发,API接入与推送事件(1)

    博客好久没有更新了,今天说说微信开发.微信开发的好多初学者都会又这样的迷惑,微信开发到底是什么?其实微信开发本质我和我们的网站开发没有太大的区别.我们常说的微信开发也就是公众号开,微信公众号分为三个类 ...

  8. 一周总结:AutoEncoder、Inception 、模型搭建及下周计划

    一周总结:AutoEncoder.Inception .模型搭建及下周计划   1.AutoEncoder: AutoEncoder: 自动编码器就是一种尽可能复现输入信号的神经网络:自动编码器必须捕 ...

  9. input输入框限制输入正整数、小数、字母、文字

    有的时候需要限制input的输入格式: 例如,输入大于0的正整数 <input onkeyup="if(this.value.length==1){this.value=this.va ...

  10. 如何从RxJava升级到RxJava2

    如何从RxJava升级到RxJava2. RxJava2已经推出有一年半的时间,由于之前RxJava已经在现有项目中广泛使用,而RxJava2在除了很多命名外并没有太多革新,所以相信有很多人跟我一样都 ...