はまやんはまやんはまやん

hamayanhamayan's blog

Restoring Road Network [AtCoder Regular Contest 083 / AtCoder Beginner Contest 074 D]

https://beta.atcoder.jp/contests/arc083/tasks/arc083_b

解説

https://beta.atcoder.jp/contests/arc083/submissions/1604142

全ての辺を張っておき、いらない辺を削除していくことで最適な答えを得る。
削除する辺はコストが大きいものから順に選んだが、小さい順でも行けるかも(よく分かってない)。
どこでもいいのである1頂点を経由して、

  • A[a][i] + A[i][b]==A[a][b]であれば、A[a][b]の辺は消せる
  • A[a][i] + A[i][b]
  • A[a][i] + A[i][b]>A[a][b]であれば、A[a][b]は必要なので何もしない(残す)

これを順にやって答え

typedef long long ll;
int N, A[303][303];
ll d[303][303];
#define INF INT_MAX/2
//---------------------------------------------------------------------------------------------------
void _main() {
    cin >> N;
    rep(i, 0, N) rep(j, 0, N) cin >> A[i][j];
 
    vector<pair<ll, pair<int, int>>> v;
    rep(i, 0, N) rep(j, i + 1, N) v.push_back({ -A[i][j],{ i,j } });
    sort(v.begin(), v.end());
 
    ll ans = 0;
    rep(i, 0, N) rep(j, i + 1, N) ans += A[i][j];
    fore(p, v) {
        ll c = -p.first;
        int a = p.second.first;
        int b = p.second.second;
        if (A[a][b] == INF) continue;
 
        rep(i, 0, N) if (i != a && i != b && A[a][i] != INF && A[i][b] != INF) {
            if (A[a][i] + A[i][b] == c) {
                ans -= c;
                A[a][b] = A[b][a] = INF;
                break;
            } else if (A[a][i] + A[i][b] < c) {
                printf("-1\n");
                return;
            }
        }
    }
    cout << ans << endl;
}