BZOJ3714 PA2014 Kuglarz 最小生成树

题目传送门

题意:有$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 }

猜你喜欢

转载自www.cnblogs.com/Itst/p/9783912.html
今日推荐