0%

ABC-383-E - Sum of Max Matching

思路讲解

参考洛谷题解

在kruskal的过程中求解这个问题,然后如果发现合并的复杂度太高,看看用数量代替set的合并可不可以?

然后记得结构体的全部数组要初始化

AC代码

https://atcoder.jp/contests/abc383/submissions/62364335

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
// Problem: E - Sum of Max Matching
// Contest: AtCoder - Daiwa Securities Co. Ltd. Programming Contest 2024(AtCoder Beginner Contest 383)
// URL: https://atcoder.jp/contests/abc383/tasks/abc383_e
// Memory Limit: 1024 MB
// Time Limit: 2500 ms
//
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
#define FOR(i, a, b) for (int i = a; i <= b; ++i)
#define ROF(i, a, b) for (int i = a; i >= b; --i)
#define all(x) x.begin(),x.end()
#define debug(x) cerr<<x<<'\n'

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll,ll> pll;
typedef array<ll,3> arr;
typedef double DB;
const ll MAXN=static_cast<ll>(2e5)+10,MAXval=static_cast<ll>(5e18)+3;

ll N,M,K;
vector<pll> G[MAXN];
struct Triple{
ll u,v,w;
};
struct cmp{
bool operator()(const Triple &a,const Triple &b)const{
return a.w>b.w;
}
};
priority_queue<Triple,vector<Triple>,cmp> pq;

struct FA{
// 初始每个点的未匹配点数量
ll fa[MAXN],size,numa[MAXN],numb[MAXN];
inline void init(ll range){
size=range;
FOR(i,1,size){ // 初始化并查集
fa[i]=i;
numa[i]=0;
numb[i]=0;
}
}
ll find(ll x){
if(fa[x]==x) return x;
return fa[x]=find(fa[x]);
}
inline void merge(ll a,ll b){
ll faA=find(a),faB=find(b);
fa[faA]=faB;
// 将a合并入b
numa[faB]+=numa[faA];
numb[faB]+=numb[faA];
// debug(numa[faB]);
// debug(numb[faB]);
}
inline ll match(ll a,ll b){
ll faA=find(a),faB=find(b);
ll aOption=min(numa[faA],numb[faB]),bOption=min(numb[faA],numa[faB]);
numa[faA]-=aOption;
numb[faB]-=aOption;
numb[faA]-=bOption;
numa[faB]-=bOption;
return aOption+bOption;
}
};

int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>N>>M>>K;
FA fa;
fa.init(N);
FOR(i, 1, M){
ll u,v,w;
cin>>u>>v>>w;
G[u].push_back({v,w});
G[v].push_back({u,w});
pq.push((Triple){u,v,w});
}
FOR(i,1,K){
ll a;
cin>>a;
fa.numa[a]+=1;
}
FOR(i,1,K){
ll b;
cin>>b;
fa.numb[b]+=1;
}
// FOR(i,1,N){
// cerr<<fa.numa[i]<<' ';
// }
// cerr<<'\n';
// FOR(i,1,N){
// cerr<<fa.numb[i]<<' ';
// }
// cerr<<'\n';
ll ans=0;
// kruskal(最小生成树+无向图判环)
while(!pq.empty()){
ll u=pq.top().u,v=pq.top().v,w=pq.top().w;
pq.pop();
if(fa.find(u)!=fa.find(v)){
ans+=w*fa.match(u,v);
// cerr<<u<<' '<<v<<' '<<w<<' '<<ans<<' '<<'\n';
fa.merge(u,v);
}
}
cout<<ans<<'\n';
return 0;
}
/*

*/

心路历程(WA,TLE,MLE……)

https://atcoder.jp/contests/abc383/submissions/62364233

类的数组记得要init()

1
2
3
4
5
6
7
8
inline void init(ll range){
size=range;
FOR(i,1,size){ // 初始化并查集
fa[i]=i;
numa[i]=0;
numb[i]=0;
}
}