競技プログラミング日記

主に AtCoder の記事です

AtCoder Beginner Contest 237E

ABC237E

ポテンシャル,ダイクストラ

まず,登りが下りのコストの \(-1\) 倍の場合を考える. これは簡単で,始点と終点のみで決まる.

次に,登りが下りのコストの \(-2\) 倍の場合を考える. この場合,\(s\)から\(t\)へのコストは,
\(H_{s} - H_{t} + \) (登りのコストの合計)
となる.ここで,登りのコストの合計は負になる.

コストの最大化を考えると,登りのコストの最大化を考えることになる. これは,登りのコストを \(-1\) 倍して正のコストにすれば, 正(または0)のコストの最小化となる. よって Dijikstra 法で求まる.

実装:
登りの合計だけ知りたいので, 下りのコストは \(0\) とする. そうしておかないと,グラフが途切れてしまう.

使っている記号,マクロ等 "https://ecsmtlir.hatenablog.com/entry/2022/12/23/131925"

int main() {
  ll n, m;
  cin >> n >> m;
  vll a(n); rep(i,n) { cin >> a[i]; }
  vector<vector<pll>> to(n);
  rep(i,m){
    ll x,y; cin >> x >> y;
    --x, --y;

    if(a[x] > a[y]) swap(x,y);
    to[x].emplace_back(y, a[y]-a[x]);  // 登りの合計のminだけ求める
    to[y].emplace_back(x, 0); // 下りは 0とする

  }
 
  min_priority_queue<pll> q;
  vector<ll> dis(n, INFL);

  q.push({dis[0]=0,0});
  while(q.size()){
    auto [cd, cv] = q.top(); q.pop();

    for(auto [nv, cost]:to[cv]) {
      ll nd = cd + cost;
      if(chmin(dis[nv], nd)){
        q.push({nd,nv});
      }
    }
  }

  ll ans = -INFL;
  rep(i,n){
    ll x = a[0] - a[i] - dis[i];
    chmax(ans, x);
  }
  cout << ans << endl;
 

  return 0;
}