zoukankan      html  css  js  c++  java
  • CH-6101 (SPFA维护路径信息)

    解法参考进阶指南

    题意:找一条1到n的路径使得路径上选2个点使得之前经过的那个点的权值减之后经过的那个点的权值的值最大。

    可以用SPFA维护(维护方法与POJ-3662相似)点1到点(i)的路径上所有点的最小值(D[i]),再维护一个(i)(n)的最大值(F[i])(等价于建个反图维护(n)(i)的最大值),枚举每个点(F[i]-D[i]),取个最大值就是答案。

    const int maxn = 1e5+10;
    int val[maxn], F[maxn], D[maxn];
    bool inq[maxn];
    int n, m;
    
    vector<int> e[maxn], e2[maxn];
    
    void spfa1(int s) {
      mem(D,0x3f);
      mem(inq,0);
      queue<int> q;
      q.push(s);
      inq[s] = 1;
      D[s] = val[s];
      while (!q.empty()) {
        int u = q.front(); q.pop();
        inq[u] = 0;
        for (auto v : e[u]) {
          if (D[v] > min(D[u], val[v])) {
            D[v] = min(D[u],val[v]);
            if (!inq[v]) q.push(v), inq[v] = 1;
          }
        }
      }
    }
    
    void spfa2(int s) {
      mem(F,0);
      mem(inq,0);
      queue<int> q;
      q.push(s);
      inq[s] = 1;
      F[s] = val[s];
      while (!q.empty()) {
        int u = q.front(); q.pop();
        inq[u] = 0;
        for (auto v : e2[u]) {
          if (F[v] < max(F[u], val[v])) {
            F[v] = max(F[u], val[v]);
            if (!inq[v]) q.push(v), inq[v] = 1;
          }
        } 
      }
    }
    
    void run() {
      n = rd(), m = rd();
      rep(i,1,n) {
        val[i] = rd();
      }
      while (m--) {
        int u = rd(), v = rd(), op = rd();
        e[u].pb(v), e2[v].pb(u);
        if (op==2) e[v].pb(u), e2[u].pb(v);
      }
      spfa1(1);
      spfa2(n);
      int ans = 0;
      rep(i,1,n) ans = max(ans, F[i]-D[i]);
      pnt(ans);
    }
    
  • 相关阅读:
    Android 控件的学习
    Java并发编程
    Glide的学习之路
    插件化和热修复学习之路
    OkHttp的学习
    WMS的学习
    app一点一滴的学习
    进程启动学习
    View学习之解决滑动冲突
    应用学习
  • 原文地址:https://www.cnblogs.com/hznudreamer/p/13780791.html
Copyright © 2011-2022 走看看