BZOJ3058 四叶草魔杖

Poetize11的T3

蒟蒻非常欢脱的写完了费用流,发现。。。边的cost竟然只算一次!!!

然后就跪了。。。

Orz题解:"类型:Floyd传递闭包+最小生成树+状态压缩动态规划
首先Floyd传递闭包,然后找出所有∑ai =0的集合,对每个集合求出最小生成树,就是该集合内部能量转化的最小代价。
然后把每个集合当做一个物品,做一遍类似背包的DP。DP过程中F[i]表示二进制状态为i(1表示该点选了,0表示没选)时已选的点之间能量转化的最小代价。然后枚举所有的j,如果i and j=0,那么用F[i]+F[j]更新一下F[i or j]。
直接这样DP可能会超时,我们不妨去除一些诸如ai=0之类的点。然后把∑ai=0的集合存进数组,DP时只循环数组内的状态来加速。"

原来Floyd还有如此妙用= =

 1 /**************************************************************
 2     Problem: 3058
 3     User: rausen
 4     Language: C++
 5     Result: Accepted
 6     Time:36 ms
 7     Memory:1580 kb
 8 ****************************************************************/
 9
10 #include <cstdio>
11 #include <cstring>
12 #include <algorithm>
13
14 using namespace std;
15 const int N = 20, M = 65536;
16
17 int n, m, p, q, l, t;
18 int a[N], d[N][N], g[N], b[M], c[N], f[M], s[M];
19 bool vis[N];
20
21 inline int read() {
22     int x = 0, sgn = 1;
23     char ch = getchar();
24     while (ch < ‘0‘ || ‘9‘ < ch) {
25         if (ch == ‘-‘) sgn = -1;
26         ch = getchar();
27     }
28     while (‘0‘ <= ch && ch <= ‘9‘) {
29         x = x * 10 + ch - ‘0‘;
30         ch = getchar();
31     }
32     return sgn * x;
33 }
34
35 int prim() {
36     int res = 0, i, j, k, tmp;
37     memset(vis, 0, sizeof(vis));
38     memset(g, 0x3f, sizeof(g));
39     g[c[1]] = 0;
40     for (i = 1; i <= m; ++i) {
41         tmp = 0x3fffffff;
42         for (j = 1; j <= m; ++j)
43             if (!vis[c[j]] && g[c[j]] < tmp) tmp = g[c[j]], k = c[j];
44         if (tmp == 0x3f3f3f3f) return -1;
45         res += tmp;
46         vis[k] = 1;
47         for (j = 1; j <= m; ++j)
48             if (!vis[c[j]] && g[c[j]] > d[k][c[j]])
49                 g[c[j]] = d[k][c[j]];
50     }
51     return res;
52 }
53
54 void Floyd() {
55     int i, j, k;
56     for (k = 1; k <= n; ++k)
57         for (i = 1; i <= n; ++i)
58             for (j = 1; j <= n; ++j)
59                 d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
60 }
61
62 int main() {
63     int i, j, k, x, y, maxi;
64     n = read(), m = read();
65     memset(d, 0x3f, sizeof(d));
66     t = (1 << n) - 1;
67     for (i = 1; i <= n; ++i) {
68         if (!(a[i] = read())) t ^= 1 << i - 1;
69         d[i][i] = 0;
70     }
71     for (i = 1; i <= m; ++i) {
72         x = read() + 1, y = read() + 1;
73         d[x][y] = d[y][x] = read();
74     }
75     Floyd();
76     memset(f, 0x3f, sizeof(f));
77     f[0] = 0;
78     for (p = i = 0, maxi = 1 << n; i < maxi; ++i) {
79         for (j = 0; j < n; ++j)
80             if ((i >> j & 1) && !a[j + 1]) break;
81         if (j < n) continue;
82         b[i] = 0;
83         for (m = j = 0; j < n; ++j)
84             if (i >> j & 1) b[i] += a[j + 1], c[++m] = j + 1;
85         if (b[i]) continue;
86         b[i] = prim();
87         s[++p] = i;
88     }
89     for (q = 2; q <= p; ++q) {
90         i = s[q], k = b[i];
91         if (k == -1) continue;
92         for (l = 1; l <= p; ++l) {
93             j = s[l];
94             if (!(i & j)) f[i | j] = min(f[i | j], f[j] + k);
95         }
96     }
97     if (f[t] == 0x3f3f3f3f) puts("Impossible");
98     else printf("%d\n", f[t]);
99 }

时间: 2024-10-04 07:26:20

BZOJ3058 四叶草魔杖的相关文章

[tyvj2054] 四叶草魔杖 (最小生成树 状压dp)

传送门 Background 陶醉在彩虹光芒笼罩的美景之中,探险队员们不知不觉已经穿过了七色虹,到达了目的地,面前出现了一座城堡和小溪田园,城堡前的木牌上写着"Poetic Island". "这一定就是另外两位护法的所在地了--我们快进去吧!" 探险队员们快步进入了城堡,城堡大厅的羊毛沙发上坐着两个人. "你们是Nescafe的护法吧?" "是的哦~ 我们就是圣剑护法rainbow和魔杖护法freda~ 你们来这里做什么呢~"

TYVJ 2054 [Nescaf&#233;29]四叶草魔杖 最小生成树 状态压缩/背包DP

$ \rightarrow $ 戳我进TYVJ原题 [Nescafé29]四叶草魔杖 题目限制 时间限制 内存限制 评测方式 题目来源 1000ms 131072KiB 标准比较器 Local 题目背景 陶醉在彩虹光芒笼罩的美景之中,探险队员们不知不觉已经穿过了七色虹, 到达了目的地,面前出现了一座城堡和小溪田园,城堡前的木牌上写着"Poetic Island". "这一定就是另外两位护法的所在地了--我们快进去吧!" 探险队员们快步进入了城堡,城堡大厅的羊毛沙发上

tyvj 2054 [Nescaf&#233;29]四叶草魔杖——最小生成树+状压dp

题目:http://www.joyoi.cn/problem/tyvj-2054 枚举点集,如果其和为0,则作为一个独立的块求一下最小生成树.因为它可以不和别的块连边. 然后状压dp即可. 别忘了判断该块能不能连通. 别忘了判断无解!(0x3f 真好用) #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const in

11.10晚间练习赛 一套全场爆零的好题

11.10晚间练习赛 一套全场爆零的好题 nodgd改的题面是真的令人不解 T1 数正方形 题面: 在\(N * N\)的点阵中任取4个点,回答: 问题1:这4个点恰好是"正放"的正方形的4个顶点的方案数是多少? 问题2:这4个点恰好是正方形(包括"正放"和"斜放")的4个顶点的方案数是多少? 下图为一个4*4的点阵,左图表示一种"正放"的方案,右图表示一种"斜放"的方案. ------ 看出来了就是水题

四叶草

在图形输出窗口中动态绘制四叶草. 1 #include <graphics.h> 2 #include <math.h> 3 #include <conio.h> 4 #define PI 3.1415926535 5 void main(void) 6 { 7 initgraph(640,480); 8 setcolor(GREEN); 9 setorigin(320,240); 10 double e; 11 int x1,y1,x2,y2; 12 for(doub

洛谷P1584 魔杖

题目描述 Smart在春游时意外地得到了一种好东西--一种非常珍贵的树枝.这些树枝可以用来做优质的魔杖! 选择怎样的切割方式来制作魔杖非常重要,关键问题是--一把魔杖既不能太长.又不能太短,且制作出来的魔杖不能有冲突-- Smart得到的这些树枝在属性上完全相同.每一根树枝都有n段(用1~n编号),给定了每段的长度L和每段的魔力值M.你可以做的就是选择一段或连续的几段,把它们作为一个整体切下来,再用来制作魔杖.但是一根魔杖的长度不能太长,不能大于给定的值hi:也不能太短,不能小于给定的值low.

四叶草黑苹果启动器Clover EFI bootloader v2.4k r4961最新版

Clover EFI bootloader  Mac版也是基于EFI的启动加载程序.用大多数用户的话来说就是一个黑苹果启动器,它能够帮助用户快速的启动装置,能让您在安装了多个操作系统的时候,为您针对BIOS的计算机创建一个EDK2/Duet启动加载程序作为代替,您要编译它,需要将其四叶草源添加到edk2/文件夹中.Clover EFI Mac版使用简单,功能强大,是您系统装机必备启动程序. Clover bootloader软件介绍 上个月苹果公司更新了 macOS Mojave系统,也是10.

Windows环境下使用Clover四叶草引导双硬盘安装OSX 10.11.5原版镜像

作为一个穷逼大学生,想搞iOS开发 买不起Mac只能鼓捣鼓捣黑苹果啦........ 之前我的电脑通过变色龙引导的方式装了个OSX10.10和win8.1双系统,因为自学的是Swift语言之前装的OSX10.10.4的Xcode(6.多版本的)只支持到Swift1.2,所以现在要装个OSX10.11.5的系统搞搞iOS开发.电脑硬盘差不多快装满了所以这次准备把OSX10.11.5装到我的移动硬盘上.因为电脑已经装过一个OSX10.10所以还用变色龙的话 出了一堆奇奇怪怪的问题.扯淡的不行.所以这

vijos 1285&amp;1283&amp;1282&amp;1284 佳佳的魔法药水/魔杖/魔法照片/魔法阵

题目链接: https://vijos.org/p/1285 https://vijos.org/p/1283 https://vijos.org/p/1282 https://vijos.org/p/1284