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)\)