Erasing Vertices 2

Erasing Vertices 2

题意

给定一个 \(n\) 个点 \(m\) 条边的简单无向图。点 \(i\) 上有一个正整数点权 \(a_i\),做 \(n\) 此操作,每次选择一个点 \(x\),删掉这个点的代价是与它相连的点(没被删掉)的点权之和,问 \(n\) 次操作的代价最大值最小是多少。

思路

显然,代价最小的肯定能被删掉,所以先删最小的,只有删了最小的,才能影响大的能被删掉,所以用个单调队列记录代价最小的然后一点一点的更新与删除。

代码

#include <iostream>
#include <algorithm>
#include <queue>

using namespace std;
using ll = long long;

const int MaxN = 2e5 + 10;

struct S {
  ll x, t;

  bool operator<(const S &j) const {
    return t > j.t;
  }
};

ll a[MaxN], d[MaxN], n, m, ans;
priority_queue<S> q;
vector<int> g[MaxN];
bool vis[MaxN];

int main() {
  cin >> n >> m;
  for (int i = 1; i <= n; i++) {
    cin >> a[i];
  }
  for (int i = 1, u, v; i <= m; i++) {
    cin >> u >> v;
    g[u].push_back(v);
    g[v].push_back(u);
    d[u] += a[v], d[v] += a[u];
  }
  for (int i = 1; i <= n; i++) {
    q.push({i, d[i]});
  }
  while (!q.empty()) {
    S u = q.top();
    q.pop();
    if (vis[u.x]) {
      continue;
    }
    vis[u.x] = 1, ans = max(ans, u.t);
    for (int i : g[u.x]) {
      q.push({i, (d[i] -= a[u.x])});
    }
  }
  cout << ans << endl;
  return 0;
}

时间复杂度

更新与删除:\(O(n+m)\)

总共:\(O(n + m)\)

posted @ 2023-05-17 20:42  yabnto  阅读(16)  评论(0编辑  收藏  举报