uoj 176 新年的繁荣 - 贪心 - 并查集

题目传送门

  传送门

题目大意

  每个点有一个点权$a_i$,连接点$u$和点$v$的边的边权是$a_u\ and\ a_v$,问最大生成树。

  我们从大到小考虑每一种边权,如果两个未连通的点的点权同时包含这个边权作为子集,显然用这样的边连接这些点最优。

  因此每一种已经考虑过的边权,我们用并查集取一个代表元。

  每枚举到一个新的边权就尝试合并一些已有的连通块。

Code

 1 /**
 2  * uoj
 3  * Problem#176
 4  * Accepted
 5  * Time: 1128ms
 6  * Memory: 3276k
 7  */
 8 #include <iostream>
 9 #include <cstdlib>
10 #include <cstdio>
11 #ifndef WIN32
12 #define Auto "%lld"
13 #else
14 #define Auto "%I64d"
15 #endif
16 using namespace std;
17 typedef bool boolean;
18
19 #define ll long long
20
21 template <typename T>
22 void pfill(T* pst, const T* ped, T val) {
23     for ( ; pst != ped; *(pst++) = val);
24 }
25
26 int n, m;
27 int S;
28 int *f, *ar;
29 ll res = 0;
30
31 int find(int x) {
32     return (f[x] == x) ? (x) : (f[x] = find(f[x]));
33 }
34
35 inline void init() {
36     scanf("%d%d", &n, &m);
37     S = 1 << m;
38     f = new int[S];
39     ar = new int[S];
40     pfill(ar, ar + S, 0);
41     for (int i = 1, x; i <= n; i++) {
42         scanf("%d", &x);
43         if (!ar[x])
44             f[x] = x, ar[x] = x;
45         else
46             res += x;
47     }
48 }
49
50 inline void solve() {
51     for (int s = S - 1, x, y; s; s--) {
52         for (int i = 0; !ar[s] && i < m; ar[s] |= ar[s | (1 << (i++))]);
53         if (!(x = ar[s]))
54             continue;
55         for (int i = 0; i < m; i++)
56             if (ar[s | (1 << i)]) {
57                 y = find(ar[s | (1 << i)]);
58                 if (y ^ find(x)) {
59                     f[y] = find(x), ar[s] = find(x);
60                     res += s;
61                 }
62             }
63     }
64     printf(Auto, res);
65 }
66
67 int main() {
68     init();
69     solve();
70     return 0;
71 }

原文地址:https://www.cnblogs.com/yyf0309/p/9880278.html

时间: 2024-10-07 05:23:01

uoj 176 新年的繁荣 - 贪心 - 并查集的相关文章

贪心 + 并查集 之 CODE[VS] 1069 关押罪犯 2010年NOIP全国联赛提高组

/* 贪心 + 并查集 之 CODE[VS] 1069 关押罪犯  2010年NOIP全国联赛提高组 两座监狱,M组罪犯冲突,目标:第一个冲突事件的影响力最小. 依据冲突大小,将M组罪犯按从大到小排序,按照排序结果,依次把每组罪犯分开放入两个监狱, 直到当前这组罪犯已经在同一个监狱中了,此时即为答案. 实现: 1)通过不在同一个监狱的罪犯,推断出在同一个监狱的罪犯.(依据:一共就两个监狱)      ftr[b] = a+n   // a和b是在不同监狱 ftr[c] = a+n   // a和

poj 1456 Supermarket (贪心+并查集)

# include <stdio.h> # include <algorithm> # include <string.h> using namespace std; int fa[10010]; struct node { int p; int d; }; struct node a[10010]; bool cmp(node a1,node a2)//利润从大到小 { return a1.p>a2.p; } int find(int x) { if(fa[x]

Codeforces 437D The Child and Zoo(贪心+并查集)

题目链接:Codeforces 437D The Child and Zoo 题目大意:小孩子去参观动物园,动物园分很多个区,每个区有若干种动物,拥有的动物种数作为该区的权值.然后有m条路,每条路的权值为该条路连接的两个区中权值较小的一个.如果两个区没有直接连接,那么f值即为从一个区走到另一个区中所经过的路中权值最小的值做为权值.问,平均两个区之间移动的权值为多少. 解题思路:并查集+贪心.将所有的边按照权值排序,从最大的开始连接,每次连接时计算的次数为连接两块的节点数的积(乘法原理). #in

Codeforces 437D 贪心+并查集

这个题目让我想起了上次在湘潭赛的那道跪死了的题.也是最值问题,这个也是,有n个动物园 每个都有权值 然后被m条路径相连接,保证图是连通的,然后求所有的p[i][j]之和.i,j为任意两个zoo,pij就为i到j路上遇到的包括i j在内的最小权值的zoo 然后我就焦头烂额了一下,这个明显就是看某个最小值为最后的结果发挥了多少次作用,但这个是图,要知道某个节点到底给多少条路径贡献出了最小值,还真是有点没头绪(在已知的复杂度一看 最多只能用nlogn的),最后是看了解答才知道的 用并查集来解决某个最小

POJ 1456 贪心 并查集

看一下中文版的题目就好,英文题目太晦涩了. 有两种方法可以解题 一种是贪心+优先队列 另一种是贪心+并查集 优先队列  需要说的都在代码注释里 #include<cstdio> #include<queue> #include<algorithm> using namespace std; struct s{ int day, val; }arr[100005]; bool cmp(s a, s b){ if(a.day != b.day) return a.day &

GYM 101173 F.Free Figurines(贪心||并查集)

原题链接 题意:俄罗斯套娃,给出一个初始状态和终止状态,问至少需要多少步操作才能实现状态转化 贪心做法如果完全拆掉再重装,答案是p[i]和q[i]中不为0的值的个数.现在要求寻找最小步数,显然要减去一些多余的步数.如果初始的一些链的前端是终止的某一条链的连续的一部分,那么这条链就不用被拆开再连上,这样每一个长度为x的链对答案的贡献就是-2*(x-1),对每条链进行同样的操作之后就是答案 #include <iostream> #include<cstdio> #include<

(贪心 + 并查集优化) poj 1456

Supermarket Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 9452   Accepted: 4067 Description A supermarket has a set Prod of products on sale. It earns a profit px for each product x∈Prod sold by a deadline dx that is measured as an int

Supermarket poj 1456 贪心+并查集优化

Language: Default Supermarket Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 9512   Accepted: 4096 Description A supermarket has a set Prod of products on sale. It earns a profit px for each product x∈Prod sold by a deadline dx that is

HDU 2480 - Steal the Treasure(贪心+并查集)

Steal the Treasure Time Limit: 10000/6000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Problem Description The alliance of thieves decides to steal the treasure from country A. There are n cities in country A. Cities are connected by