CF1408E Avoid Rainbow Cycles
没什么好狡辩的,就是根本想不到(苦笑
其实看起来就很像是需要构图的样子,对于所有 \(j \in A_i\),我们连一条无向边 \((j, A_i)\)。
容易发现若原图中有一个环,那么新图也会对应一个环(可以借助这个事实来理解:即连向同一个 \(A_i\) 的两个点在原图中是相连的)
所以问题转化成花最少的代价删边使新图不含环。直接最大生成树就可以了。时间复杂度 \(O(\sum s_i \log {\sum s_i})\)。
#include<bits/stdc++.h>
#define F(i,l,r) for(int i(l); i <= (r); ++ i)
#define G(i,r,l) for(int i(r); i >= (l); -- i)
#define int ll
using namespace std;
using ll = long long;
const int N = 4e5;
struct node{
int u, v, w;
bool operator < (const node &other)const{
return w > other.w;
}
}e[N];
int n, m, cnt, sum = 0, tt = 0;
int a[N], b[N], fa[N];
int getfather(int x){
if(fa[x] != x) fa[x] = getfather(fa[x]);
return fa[x];
}
void kru(){
F(i, 1, cnt){
int u, v, w;
u = getfather(e[i].u);
v = getfather(e[i].v);
w = e[i].w;
if(u != v){
fa[u] = v;
tt += w;
}
}
}
signed main(){
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
cin >> m >> n;
F(i, 1, n + m) fa[i] = i;
F(i, 1, m) cin >> a[i];
F(i, 1, n) cin >> b[i];
F(i, 1, m){
int s;
cin >> s;
F(j, 1, s){
int x;
cin >> x;
e[++ cnt] = (node){i + n, x, a[i] + b[x]};
sum += a[i] + b[x];
}
}
sort(e + 1, e + cnt + 1);
kru();
// printf("The weight of MaxTree = %lld\n", tt);
cout << sum - tt << '\n';
return fflush(0), 0;
}

浙公网安备 33010602011771号