• 题解【luogu1073 最优贸易】


    Solution

    考虑原图是 DAG 时怎么做。

    拓扑排序 + dp ,令 dp[i] 表示 (1)(i) 的路径上最小的卖出价格。转移方程就是对每一个可以到达这个点的 dp 取个 min ,计算答案便是 (max limits _{i} {val_i - dp_i }) ,其中 val 是商品价格。dp 在拓扑序上随便转移一下就好

    考虑题目怎么做便十分显然,直接缩点得到一张 DAG ,贪心的让缩完的点的卖出价格是该点中价值最大的,卖入的是该点中价值最小的。然后就可以用在 DAG 上转移的方法来做就可以了

    A Very Important thing :

    在更新答案的时候,需要判断这个点是否能到达 n 点所在的强连通分量里。实现方法是在 反图上 dfs 一遍就可以判断出那些点能够到达终点。

    Code

    #include <bits/stdc++.h>
    #define INF 1000000000
    using namespace std;
    const int N = 100100;
    const int M = 500500; 
    int n, m, val[N], cnt, dfn[N], low[N], tot, U[N], V[N], ind[N], ins[N], vis[N]; 
    int scc, bel[N], Max[N], Min[N], List[N], ans, dp[N], sta[N], top, z[N]; 
    struct edge {
      int v; edge *next; 
    }pool[M * 6], *head[N], *h[N], *hh[N];
    inline void addd(int u, int v) {
      edge *p = &pool[++cnt];
      p->v = v, p->next = hh[u], hh[u] = p;
    }
    inline void add(int u, int v) {
      edge *p = &pool[++cnt];
      p->v = v, p->next = h[u], h[u] = p; 
    }
    inline void addedge(int u, int v) {
      edge *p = &pool[++cnt];
      p->v = v, p->next = head[u], head[u] = p; 
    }
    inline void tarjan(int u) {
      dfn[u] = low[u] = ++tot; ins[u] = 1, sta[++top] = u; 
      for(edge *p = head[u]; p; p = p->next) {
        int v = p->v; 
        if(!dfn[v]) tarjan(v), low[u] = min(low[u], low[v]);
        else if(ins[v]) low[u] = min(low[u], dfn[v]); 
      } if(low[u] == dfn[u]) {
        ++scc;
        while(sta[top + 1] != u) {
          Max[scc] = max(Max[scc], val[sta[top]]);
          Min[scc] = min(Min[scc], val[sta[top]]); 
          bel[sta[top]] = scc; ins[sta[top--]] = 0; 
        }
      }
    }
    inline void toposort() {
      tot = 0; queue <int> Q; 
      while(!Q.empty()) Q.pop();
      for(int i = 1; i <= scc; i++)
        if(!ind[i]) Q.push(i);
      while(!Q.empty()) {
        int u = Q.front(); Q.pop();
        List[++tot] = u;
        for(edge *p = h[u]; p; p = p->next) {
          int v = p->v; ind[v]--;
          if(ind[v] == 0) Q.push(v); 
        }
      }
    }
    inline void dfs(int u) {
      if(vis[u]) return ; vis[u] = 1; 
      for(edge *p = hh[u]; p; p = p->next) dfs(p->v); 
    }
    int main() {
      scanf("%d %d", &n, &m); 
      for(int i = 1; i <= n; i++) scanf("%d", &val[i]);
      for(int i = 1; i <= n; i++) Min[i] = INF, Max[i] = -INF;
      for(int i = 1; i <= m; i++) {
        scanf("%d %d %d", &U[i], &V[i], &z[i]);
        addedge(U[i], V[i]); 
        if(z[i] == 2) addedge(V[i], U[i]); 
      } 
      for(int i = 1; i <= n; i++) 
        if(!dfn[i]) tarjan(i); 
      for(int i = 1; i <= m; i++) {
        int x = bel[U[i]], y = bel[V[i]];
        if(x != y) { add(x, y), ind[y]++, addd(y, x); 
          if(z[i] == 2) add(y, x), ind[x]++, addd(x, y); 
        }
      } toposort(); dfs(bel[n]); 
      for(int i = 1; i <= scc; i++) dp[i] = Min[i]; 
      for(int i = 1; i <= scc; i++) {
        int u = List[i]; 
        if(vis[u]) ans = max(ans, Max[u] - dp[u]);
        for(edge *p = h[u]; p; p = p->next) {
          int v = p->v; dp[v] = min(dp[v], dp[u]); 
        }
      } 
      printf("%d
    ", ans);
      return 0; 
    } 
    
  • 相关阅读:
    养生与健康
    vue + elementui 使用多选按钮实现单选功能
    生活小方
    和业务相关的工具函数
    vue + element ui开发过程中需要注意的几个点
    【转】webpack中关于source map的配置
    【转】移动前端手机输入法自带emoji表情字符处理
    webpack相关
    vue项目优化
    运维集群架构演变之美 【转】
  • 原文地址:https://www.cnblogs.com/acfunction/p/10060606.html
Copyright © 2020-2023  润新知