题意:有$N$个盒子,每个盒子中有$0$或$1$个球。现在你可以花费$c_{i,j}$的代价获得$i$到$j$的盒子中球的总数的奇偶性,求最少需要多少代价才能知道哪些盒子中有球。$N \leq 2000 , 1 \leq c \leq 10^9$
初赛凉了,乖乖回来更以前没写的blog qwq
设$s_i$为盒子中球数的前缀和$(s_0 = 0)$,那么我们花费$c_{i,j}$就是得到$s_{i-1}$与$s_j$的关系,而我们知道$s_i,s_j$与$s_j,s_k$的关系之后,就能知道$s_i$与$s_k$的关系。我们可以考虑使用并查集维护这个关系,然后:咦这不就是$Kruskal$吗?然后跑遍最小生成树就出来了
反正我是有生之年不会想到这道题和最小生成树相关的了QuQ
还有Prim用堆优化真心卵用没有
1 #include<bits/stdc++.h>
2 #define MAXN 2001
3 using namespace std;
4 inline int read(){
5 int a = 0;
6 bool f = 0;
7 char c;
8 fread(&c , sizeof(char) , 1 , stdin);
9 while(!isdigit(c)){
10 if(c == '-')
11 f = 1;
12 fread(&c , sizeof(char) , 1 , stdin);
13 }
14 while(isdigit(c)){
15 a = (a << 3) + (a << 1) + (c ^ '0');
16 fread(&c , sizeof(char) , 1 , stdin);
17 }
18 return f ? -a : a;
19 }
20 int Edge[MAXN][MAXN];
21 bool vis[MAXN];
22 priority_queue < pair < int , int > > q;
23 int main(){
24 long long ans = 0;
25 int N = read();
26 for(int i = 1 ; i <= N ; i++)
27 for(int j = i ; j <= N ; j++)
28 Edge[i - 1][j] = Edge[j][i - 1] = read();
29 q.push(make_pair(0 , 0));
30 while(!q.empty()){
31 int t = q.top().second;
32 if(vis[t]){
33 q.pop();
34 continue;
35 }
36 ans += -q.top().first;
37 vis[t] = 1;
38 q.pop();
39 for(int i = 0 ; i <= N ; i++)
40 if(!vis[i])
41 q.push(make_pair(-Edge[t][i] , i));
42 }
43 cout << ans;
44 return 0;
45 }