• 题解【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; 
    } 
    
  • 相关阅读:
    Interview with BOA
    Java Main Differences between HashMap HashTable and ConcurrentHashMap
    Java Main Differences between Java and C++
    LeetCode 33. Search in Rotated Sorted Array
    LeetCode 154. Find Minimum in Rotated Sorted Array II
    LeetCode 153. Find Minimum in Rotated Sorted Array
    LeetCode 75. Sort Colors
    LeetCode 31. Next Permutation
    LeetCode 60. Permutation Sequence
    LeetCode 216. Combination Sum III
  • 原文地址:https://www.cnblogs.com/acfunction/p/10060606.html
Copyright © 2020-2023  润新知