计蒜客 - 42580 Bob‘s Problem(ICPC2019 南昌站)

it2023-08-30  66

题目 Bob was in trouble.He rubbed the magic ring on his finger, and you came out of the ground.

You are given an undirected graph G which contains n vertices labelled from 1 to n, with m weighted edges between them coloured in black or white.You have to choose some edges in G such that there is at least one path between any two vertices only passing by selected edges, and you can select no more than k white edges.There may be multiple available strategies to determine these edges, and you are asked to find out the way with a maximum total weight of edges.

Input The first line contains an integer T (1≤T≤5) indicating the number of test cases.

For each test case, the first line contains three integers n (1≤n≤50000),m and k (1≤k≤m≤500000).

Each of the following m lines contains four integers u,v (1≤u,v≤n),w (0≤w≤100000) and c (0≤c≤1) describing an edge of weight w and colour c between the u-th vertex and the v-th vertex. Here an edge is white if c=1, or black if c=0.

Note that there may be multiple edges between some vertices, and self-loops are also allowed.

Output For each test case, output a single line with an integer indicating the maximum total weight of selected edges, or output -1 if there is no solution for the given graph.

Sample Input 1 5 6 2 1 2 0 0 1 3 5 1 1 5 1 0 2 3 6 1 2 4 2 0 3 4 7 1 Sample Output 16

题意 给n个结点编号1~n,给m个有边权的边,边又分为白边与黑边,标记出其中若干个边,其中白边最多只能标记k条,令其中任何两个点都有一条路径只经过被标记的边,输出被标记的边权和,如果有多解,输出其中边权和最大的一种情况。

思路 因为黑边可以任意选,先选出所有黑边,并把其中黑边所连接的点标记出来,然后按边权从大到小遍历全部白边,如果能够选出k条白边令整个图联通就有解,反之无解。 PS.思路很简单,但是我码代码的能力实在太弱,本来一道水题代码写的又臭又长,好在一发a了,不然改代码能让我痛苦死………… 代码

#include<bits/stdc++.h> using namespace std; #define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0) #define ll long long const int MAXN = 5e4 + 5, MAXM = 5e5 + 5; int t, n, m, k; struct node { int u, v, w; }white[MAXM], black[MAXM]; int wnum, bnum; int vis[MAXN], jud[MAXN], cnt[MAXN]; bool cmp(node a, node b) { return a.w > b.w; } int main(void){ IO; cin >> t; while(t--) { memset(vis,0,sizeof(vis)); memset(jud,0,sizeof(jud)); memset(cnt,0,sizeof(cnt)); memset(white,0,sizeof(white)); memset(black,0,sizeof(black)); wnum = 0, bnum = 0; cin >> n >> m >> k; for(int i = 0; i < m; i++) { int c;node x;cin >> x.u >> x.v >> x.w >> c; if(c)white[++wnum] = x; else black[++bnum] = x; } jud[1] = 1;int num = 0, now = 1; ll ans = 0; for(int i = 1; i <= bnum; i++) { if(!vis[black[i].u])vis[black[i].u] = 1,num++; if(!vis[black[i].v])vis[black[i].v] = 1,num++; ans += black[i].w; } sort(white + 1, white + wnum + 1, &cmp); queue<int> q; for(int i = 1; i <= wnum; i++) { if(!vis[white[i].u] && !vis[white[i].v]) { ans += white[i].w; k--; now++; vis[white[i].u] = now; vis[white[i].v] = now; cnt[now] += 2; }else if(!vis[white[i].u]) { ans += white[i].w; k--; vis[white[i].u] = vis[white[i].v]; cnt[vis[white[i].v]]++; if(jud[vis[white[i].v]])num++; }else if(!vis[white[i].v]) { ans += white[i].w; k--; vis[white[i].v] = vis[white[i].u]; cnt[vis[white[i].u]]++; if(jud[vis[white[i].u]])num++; }else if(vis[white[i].u] == vis[white[i].v]) { q.push(white[i].w); }else if(vis[white[i].u] != vis[white[i].v]) { if(jud[vis[white[i].u]] && jud[vis[white[i].v]]) { q.push(white[i].w); }else if(jud[vis[white[i].u]] || jud[vis[white[i].v]]) { ans += white[i].w; k--; if(jud[vis[white[i].u]])num += jud[vis[white[i].v]]; else num += jud[vis[white[i].u]]; jud[vis[white[i].u]] = jud[vis[white[i].v]] = 1; }else { int mi = min(vis[white[i].u], vis[white[i].v]), ma = max(vis[white[i].u], vis[white[i].v]); for(int i = 1; i <= n; i++) { if(vis[i] == mi)vis[i] == ma; } cnt[ma] += cnt[mi]; cnt[mi] = 0; } } if(num == n) { if(k <= 0)break; while(!q.empty()) { ans += q.front(); q.pop(); k--; if(k == 0)break; } for(int j = i + 1; j <= wnum && k > 0; j++) { ans += white[j].w; k--; } break; } } if(num == n) { if(k >= 0) { cout << ans << '\n'; }else { cout << -1 << '\n'; } }else { cout << -1 << '\n'; } } }
最新回复(0)