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还有如此妙用= =
/**************************************************************
Problem: 3058
User: rausen
Language: C++
Result: Accepted
Time:36 ms
Memory:1580 kb
****************************************************************/ #include <cstdio>
#include <cstring>
#include <algorithm> using namespace std;
const int N = , M = ; int n, m, p, q, l, t;
int a[N], d[N][N], g[N], b[M], c[N], f[M], s[M];
bool vis[N]; inline int read() {
int x = , sgn = ;
char ch = getchar();
while (ch < '' || '' < ch) {
if (ch == '-') sgn = -;
ch = getchar();
}
while ('' <= ch && ch <= '') {
x = x * + ch - '';
ch = getchar();
}
return sgn * x;
} int prim() {
int res = , i, j, k, tmp;
memset(vis, , sizeof(vis));
memset(g, 0x3f, sizeof(g));
g[c[]] = ;
for (i = ; i <= m; ++i) {
tmp = 0x3fffffff;
for (j = ; j <= m; ++j)
if (!vis[c[j]] && g[c[j]] < tmp) tmp = g[c[j]], k = c[j];
if (tmp == 0x3f3f3f3f) return -;
res += tmp;
vis[k] = ;
for (j = ; j <= m; ++j)
if (!vis[c[j]] && g[c[j]] > d[k][c[j]])
g[c[j]] = d[k][c[j]];
}
return res;
} void Floyd() {
int i, j, k;
for (k = ; k <= n; ++k)
for (i = ; i <= n; ++i)
for (j = ; j <= n; ++j)
d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
} int main() {
int i, j, k, x, y, maxi;
n = read(), m = read();
memset(d, 0x3f, sizeof(d));
t = ( << n) - ;
for (i = ; i <= n; ++i) {
if (!(a[i] = read())) t ^= << i - ;
d[i][i] = ;
}
for (i = ; i <= m; ++i) {
x = read() + , y = read() + ;
d[x][y] = d[y][x] = read();
}
Floyd();
memset(f, 0x3f, sizeof(f));
f[] = ;
for (p = i = , maxi = << n; i < maxi; ++i) {
for (j = ; j < n; ++j)
if ((i >> j & ) && !a[j + ]) break;
if (j < n) continue;
b[i] = ;
for (m = j = ; j < n; ++j)
if (i >> j & ) b[i] += a[j + ], c[++m] = j + ;
if (b[i]) continue;
b[i] = prim();
s[++p] = i;
}
for (q = ; q <= p; ++q) {
i = s[q], k = b[i];
if (k == -) continue;
for (l = ; l <= p; ++l) {
j = s[l];
if (!(i & j)) f[i | j] = min(f[i | j], f[j] + k);
}
}
if (f[t] == 0x3f3f3f3f) puts("Impossible");
else printf("%d\n", f[t]);
}
BZOJ3058 四叶草魔杖的更多相关文章
- BZOJ_3058_四叶草魔杖_kruscal+状压DP
BZOJ_3058_四叶草魔杖_kruscal+状压DP Description 魔杖护法Freda融合了四件武器,于是魔杖顶端缓缓地生出了一棵四叶草,四片叶子幻发着淡淡的七色光.圣剑护法rainbo ...
- [tyvj2054] 四叶草魔杖 (最小生成树 状压dp)
传送门 Background 陶醉在彩虹光芒笼罩的美景之中,探险队员们不知不觉已经穿过了七色虹,到达了目的地,面前出现了一座城堡和小溪田园,城堡前的木牌上写着"Poetic Island&q ...
- BZOJ.3058.四叶草魔杖(Kruskal 状压DP)
题目链接 \(2^{16}=65536\),可以想到状压DP.但是又有\(\sum A_i\neq 0\)的问题.. 但是\(2^n\)这么小,完全可以枚举所有子集找到\(\sum A_i=0\)的, ...
- tyvj 2054 [Nescafé29]四叶草魔杖——最小生成树+状压dp
题目:http://www.joyoi.cn/problem/tyvj-2054 枚举点集,如果其和为0,则作为一个独立的块求一下最小生成树.因为它可以不和别的块连边. 然后状压dp即可. 别忘了判断 ...
- tyvj 2054 [Nescafé29]四叶草魔杖【克鲁斯卡尔+状压dp】
传送:http://www.joyoi.cn/problem/tyvj-2054 来自lyd课件: 所以先预处理出各个sum为0的块,然后状压dfs取min来得到答案 #include<iost ...
- tyvj2054 四叶草魔杖——连通块 & 状压DP
题目:http://www.joyoi.cn/problem/tyvj-2054 把点分成几个连通块,和为0的几个点放在一块,在块内跑最小生成树作为这个块的代价: 然后状压DP,组成全集的最小代价就是 ...
- bzoj5038 四叶草魔杖
很有意思的最小生成树啊. 网上的题解大多是状压+最小生成树,经过我的试验,其实只要把每个联通块找出来,一个个做一次就可以了. 放一个状压的.懒得再写一个搜索找联通块 #include<cstdi ...
- [tyvj-2054][Nescafé29]四叶草魔杖 费用流
lyd讲的最小生成树的题. 道理我都懂,费用流多好写,又好调.但和一般费用流不一样的就是它走过一次后费用需调成0,但是再等回流,就恢复原状即可. #include <queue> #inc ...
- NOIP系列复习及题目集合
首先是我的酱油记了啦~: Xs的NOIP2014酱油记,持续更新中 知识点方面: noip知识点总结之--贪心 noip知识点总结之--线性筛法及其拓展 noip知识点总结之--欧几里得算法和扩展欧几 ...
随机推荐
- Codeforces Round #377 (Div. 2) D. Exams 二分
D. Exams time limit per test 1 second memory limit per test 256 megabytes input standard input outpu ...
- Servlet学习
编写Servlet应该注意的一些细节: 1: 由于客户端是通过URL地址访问web服务器中的资源,所以Servlet程序若想被外界访问,必须把servlet程序映射到一个URL地址上,这个工作在web ...
- Redis基础知识之————php-Redis 常用命令专题
Keys del,delete - 删除键 dump - 返回存储在指定键值的序列化版本. exists - 确定键是否存在 expire,setTimeout,pexpire - 设置键的生存时间( ...
- effect c++ 口诀。
常用条款,写成口诀,记住.知其所以,也要时时使用. 1)习惯c++: 联替const初. 2)构造,复制,析构: 要知默,构赋析. 若不需,明拒绝. 构析不调虚. 异不逃析构. 基析要虚函. 赋值操, ...
- Python学习(22)python网络编程
Python 网络编程 Python 提供了两个级别访问的网络服务.: 低级别的网络服务支持基本的 Socket,它提供了标准的 BSD Sockets API,可以访问底层操作系统Socket接口的 ...
- 用Volley让GridView加载网络图片
一.布局文件 总共两个布局文件,一个是GridView,还有一个是GridView的item,是NetworkImageView和TextView activity_main.xml <Rela ...
- Android提高篇之自定义dialog实现processDialog“正在加载”效果、使用Animation实现图片旋转
知识点: 1.使用imageview.textview自定义dialog 2.使用Animation实现图片旋转动画效果 3.通过自定义theme去掉dialog的title 没有使用progres ...
- mybatis动态SQL中的set标签的使用
set标记是mybatis提供的一个智能标记,我一般将其用在修改的sql中,例如以下情况: <update> update user <set> <if test=&qu ...
- 车辆管理系统之搭建框架 添加必要的数据 安装svn(二)
JAVA EE第一阶段项目——车辆管理系统.MyEclipse + MySQL +powerDesinger +tomcat +svn. 今天组长把项目的分工安排好了!这个周末两天的作业就是我的车主信 ...
- hiho_1290_demo_day
题目大意 一个MxN的矩阵,矩阵中的有些方格中有障碍物,有些没有,有一个机器人从左上角出发,它只能有两种移动方式:一直向右移动,直到遇到障碍物:一直向下移动,直到遇到障碍物. 现在可以将矩阵中 ...