Bob‘s Problem
生活随笔
收集整理的這篇文章主要介紹了
Bob‘s Problem
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
Bob’s Problem
題意:
一個有n個點的圖,其中邊分為白色和黑色,每個邊都有邊權,所選白邊的數量的數量不能超過k,問現在選擇一些邊,使得所有點連通,問最大權值是多少?
題解:
我一開始以為是最大生成樹,但是發現樣例就不對,后來隊友一說才反應過來,題目要求的是圖連通,權值最大,那我們就要盡可能多選邊,而非選n-1個邊,因為黑邊無限制,所有我們就全選黑邊,然后對于白邊,有k的數量限制,所有我們按照權值依次看加入白邊是否可以使得圖連通,如果k還有剩余再加入剩余白邊
代碼:
#include <bits/stdc++.h>using namespace std; #define ENDL "\n" typedef long long ll; typedef pair<int, int> pii; const int inf = 0x7fffffff; const int Mod = 1e9 + 7; const int maxn = 1e6 + 10;struct node {int from, to, w;bool operator<(const node &p) const { return w >= p.w; } }; int n, m; int f[maxn]; bitset<maxn> vis; vector<node> res;int find(int x) { return f[x] == x ? x : f[x] = find(f[x]); }int main() {int t, k, u, v, w, cnt;ll ans;scanf("%d", &t);while (t--) {res.clear(), vis.reset();ans = cnt = 0;scanf("%d%d%d", &n, &m, &k);for (int i = 1; i <= n; i++) f[i] = i;for (int i = 1, x; i <= m; i++) {scanf("%d%d%d%d", &u, &v, &w, &x);if (x) {res.push_back({u, v, w});} else {ans += w;int fu = find(u), fv = find(v);if (fu != fv) {f[fu] = fv;++cnt;}}}sort(res.begin(), res.end());for (int i = 0; i < res.size() && k; i++) {u = res[i].from, v = res[i].to, w = res[i].w;int fu = find(u), fv = find(v);if (fu != fv) {f[fu] = fv;--k;ans += w;++cnt;vis[i] = 1;}}for (int i = 0; i < res.size() && k; i++) {if (!vis[i]) {ans += res[i].w;--k;}}for (int i = 1; i <= n; i++) find(i);bool ok = 1;int cur = f[1];for (int i = 2; i <= n; i++) {if (cur != f[i]) {ok = 0;break;}}if (!ok || cnt != n - 1) ans = -1;printf("%lld\n", ans);}return 0; }總結
以上是生活随笔為你收集整理的Bob‘s Problem的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ICPC2019南昌区域赛
- 下一篇: L - Who is the Champ