HDU-3311-Dig The Wells
来源:互联网 发布:淘宝店铺怎样刷信誉 编辑:程序博客网 时间:2024/05/22 13:19
ACM模版
描述
题解
斯坦纳树,模版题,状压dp,还是无法很好地理解,找了大牛们的blog,感觉好高大上……
以下来自Staginner大牛的博客……
这个和一般的斯坦纳树的题目不同的地方在于挖井要加点权,但是仔细分析一下不难发现,如果1-N作为斯坦纳树的叶子节点一共有两种状态,要么挖井要么不挖井,而其他点做为叶子节点只有一种状态,就是必须挖井,否则由于这个节点就可以被删去就一定不会是最优的方案。在dp之前如果将这些叶子节点的状态都初始化好的话,后面的内容就和普通的斯坦纳树的题目就没有什么区别了,只需要考虑边权即可,另外最后合并连通块dp的时候要判断一下当前集合内是否有水,而且要用两个有水的点集合成当前这个点集。
由于要判一个连通块内有没有水,所以要多开一个二进制位表示有没有水。
另外推荐一个感觉讲斯坦纳树讲得不错的博客:http://endlesscount.blog.163.com/blog/static/821197872012525113427573/
代码
#include <stdio.h>#include <string.h>#define INF 0x3f3f3f3fconst int MAXQ = 74000;const int MAXD = 1010;const int MAXM = 10010;const int MAXS = 74;int N, M, P, first[MAXD], e, next[MAXM], v[MAXM], w[MAXM];int bit[MAXD], q[MAXQ + 10], front, rear, inq[MAXD][MAXS];int f[MAXD][MAXS], dp[MAXS];void add(int x, int y, int z){ v[e] = y, w[e] = z; next[e] = first[x], first[x] = e++;}void init(){ int i, x, y, z; memset(f, 0x3f, sizeof(f)); memset(bit, 0, sizeof(bit)); for (i = 1; i <= N + M; i++) { if (i <= N) { bit[i] = 1 << (i - 1); } scanf("%d", &z); if (i <= N) { f[i][bit[i]] = 0, f[i][bit[i] | 1 << N] = z; } else f[i][1 << N] = z; } memset(first, -1, sizeof(first)); e = 0; for (i = 0; i < P; i++) { scanf("%d%d%d", &x, &y, &z); add(x, y, z), add(y, x, z); }}int Min(int x, int y){ return x < y ? x : y;}void spfa(){ int i, x, st, y, nst; while (front != rear) { x = q[front] & 1023, st = q[front] >> 10; inq[x][st] = 0; ++front > MAXQ ? front = 0 : 0; for (i = first[x]; i != -1; i = next[i]) { y = v[i], nst = st | bit[y]; if (f[x][st] + w[i] < f[y][nst]) { f[y][nst] = f[x][st] + w[i]; if (st == nst && !inq[y][nst]) { q[rear ++] = nst << 10 | y, inq[y][nst] = 1; rear > MAXQ ? rear = 0 : 0; } } } }}void solve(){ int i, j, k, nn = 1 << (N + 1); front = rear = 0; memset(inq, 0, sizeof(inq)); for (i = 0; i < nn; i++) { for (j = 1; j <= N + M; j++) { for (k = i - 1 & i; k; k = k - 1 & i) { f[j][i] = Min(f[j][i], f[j][k | bit[j]] + f[j][i - k | bit[j]]); } if (f[j][i] < INF) { q[rear ++] = i << 10 | j, inq[j][i] = 1; rear > MAXQ ? rear = 0 : 0; } } spfa(); } memset(dp, 0x3f, sizeof(dp)); for (i = 0; i < nn; i++) { for (j = 1; j <= N + M; j++) { dp[i] = Min(dp[i], f[j][i]); } } for (i = 0; i < nn; i ++) { if (i & 1 << N) { for (j = i - 1 & i; j; j = j - 1 & i) { if (j & 1 << N) { dp[i] = Min(dp[i], dp[j] + dp[i - j | 1 << N]); } } } } printf("%d\n", dp[(1 << (N + 1)) - 1]);}int main(){ while (scanf("%d%d%d", &N, &M, &P) == 3) { init(); solve(); } return 0;}
0 0
- HDU-3311-Dig The Wells
- HDOJ 3311 Dig The Wells
- Hdu 3311 Dig The Wells (综合_斯坦纳树)
- HDU 3311 Dig The Wells(spfa+压缩DP,5级)
- hdu 3311 Dig The Wells (SteinerTree斯坦纳树)
- HDU 3311 Dig The Wells(spfa模板)
- HDU3311-Dig The Wells
- 【斯坦纳树】 HDOJ 3311 Dig The Wells
- hdu3311 - Dig The Wells (斯坦纳树 spfa + DP)
- hdu3311Dig The Wells
- Wells, Hitler and the World State
- Harry And Dig Machine HDU
- dig
- dig
- Dig Up System Information Using the Terminal
- hdu 5067 Harry And Dig Machine
- hdu 5067 Harry And Dig Machine
- HDU 5067 Harry And Dig Machine
- STM8L Power Saving : How to Implement Auto Wake-Up Mode in STM8L101xx
- IOS:unrecognized selector sent to instance
- SDWebImage的介绍与使用
- http解析
- HDU 3880 Lucky Numbers 数学题
- HDU-3311-Dig The Wells
- 前瞻java Dubbo搭建
- Cross-Validation: the right and the wrong ways
- ubuntu root远程访问设置
- jQuery插件的实现框架
- AFNetworking的介绍与理解
- mongo查询某个字段是否存在,并删除记录里的这个字段
- Mongodb嵌套文档的修改-利用数组修改器更新数据
- Python中re(正则表达式)模块学习