https://cn.vjudge.net/problem/HDU-4085

给你n,m,k ,分别表示有n个点,m条边,每条边有一个权值,表示修复这条边需要的代价

从前k个点中任取一个使其和后k个点中的某一个点,通过边连接,并且必须是一一对应,问最小的代价是多少。

先用斯坦纳树模板求出f[i][1<<k]    然后用dp[i]表示所有点为根的情况下连通状态为i的最小花费

这样我们就可以从1dp到1<<k得到答案 注意dp之前要先判总状态是否合法 再判子集是否合法 最后再进行dp更新

#include<bits/stdc++.h>
#define N 6003
#define inf 1000000000
using namespace std;
int n, m, k, tot;
int point[N], next1[N], v[N], len[N];
int f[][( << )], mi[], can[N], dp[( << )];
queue<int> p;
void add(int x, int y, int z) {
tot++;
next1[tot] = point[x];
point[x] = tot;
v[tot] = y;
len[tot] = z;
tot++;
next1[tot] = point[y];
point[y] = tot;
v[tot] = x;
len[tot] = z;
}
void spfa(int sta) {
while (!p.empty()) {
int now = p.front();
p.pop();
for (int i = point[now]; i; i = next1[i]) {
if (f[v[i]][sta] > f[now][sta] + len[i]) {
f[v[i]][sta] = f[now][sta] + len[i];
if (!can[v[i]]) {
can[v[i]] = ;
p.push(v[i]);
}
}
}
can[now] = ;
}
}
bool check(int sta) { //判断当前的状态是否满足一一对应关系
int ans = ;
for (int i = ; i < k; i++) {
if (sta & ( << i))
ans++;
if (sta & ( << (i + k)))
ans--;
}
return (ans == );
}
int main() {
int t;
scanf("%d", &t);
mi[] = ;
for (int i = ; i <= ; i++)
mi[i] = mi[i - ] * ;
for (int T = ; T <= t; T++) {
scanf("%d%d%d", &n, &m, &k);
tot = ;
memset(point, , sizeof(point));
memset(next1, , sizeof(next1));
for (int i = ; i <= m; i++) {
int x, y, z;
scanf("%d%d%d", &x, &y, &z);
add(x, y, z);
}
for (int i = ; i <= n; i++)
for (int j = ; j < mi[]; j++)
f[i][j] = inf;
for (int i = ; i <= k; i++)
f[i][mi[i - ]] = ;
int t = k;
for (int i = n - k + ; i <= n; i++)
f[i][mi[t]] = , t++;
for (int sta = ; sta < mi[t]; sta++) {
for (int i = ; i <= n; i++) {
for (int s = sta & (sta - ); s; s = sta & (s - )) {
int t = f[i][sta - s] + f[i][s];
f[i][sta] = min(f[i][sta], t);
}
if (f[i][sta] != inf)
p.push(i), can[i] = ;
}
spfa(sta);
}
for (int sta = ; sta < mi[t]; sta++) {
dp[sta] = inf;
for (int i = ; i <= n; i++)
dp[sta] = min(dp[sta], f[i][sta]);
}
for (int sta = ; sta < mi[t]; sta++)
if (check(sta))
for (int s = sta & (sta - ); s; s = sta & (s - ))
if (check(s))
dp[sta] = min(dp[sta], dp[s] + dp[sta - s]);
if (dp[mi[t] - ] == inf)
printf("No solution\n");
else
printf("%d\n", dp[mi[t] - ]);
}
}

HDU 4085 斯坦纳树+DP的更多相关文章

  1. HDU 4085 斯坦纳树

    题目大意: 给定无向图,让前k个点都能到达后k个点(保护地)中的一个,而且前k个点每个需要占据后k个中的一个,相互不冲突 找到实现这个条件达到的选择边的最小总权值 这里很容易看出,最后选到的边不保证整 ...

  2. hdu 3311 斯坦纳树

    思路:虚拟一个0号节点,将每个点建一条到0号节点的边,权值为挖井需要的价值.并要保证0号节点同另外n个寺庙一样被选择即可. 然后就是求斯坦纳树了. #include<map> #inclu ...

  3. 【hdu3311】Dig The Wells(斯坦纳树+dp)

    传送门 题意: 给出\(n\)个重要点,还有其余\(m\)个点,\(p\)条边. 现在要在这\(n+m\)个点中挖几口水井,每个地方的费用为\(w_i\).连接边也有费用. 问使得这\(n\)个地点都 ...

  4. 【bzoj4006】[JLOI2015]管道连接(斯坦纳树+dp)

    题目链接 题意: 给出\(n\)个点,\(m\)条边,同时给出\(p\)个重要的点以及对应特征. 现在要选出一些边,问使得这\(p\)个所有特征相同的点相连,问最小代价. 思路: 斯坦纳树的应用场景一 ...

  5. [WC2008]游览计划(斯坦纳树)

    [Luogu4294] 题解 : 斯坦纳树 \(dp[i][j]\) 表示以\(i\)号节点为根,当前状态为\(j\)(与\(i\)连通的点为\(1\)) 当根\(i\)不改变时状态转移方程是: \( ...

  6. HDU 4085 Peach Blossom Spring 斯坦纳树 状态压缩DP+SPFA

    状态压缩dp+spfa解斯坦纳树 枚举子树的形态 dp[i][j] = min(dp[i][j], dp[i][k]+dp[i][l]) 当中k和l是对j的一个划分 依照边进行松弛 dp[i][j]  ...

  7. 【BZOJ2595】游览计划(状压DP,斯坦纳树)

    题意:见题面(我发现自己真是越来越懒了) 有N*M的矩阵,每个格子有一个值a[i,j] 现要求将其中的K个点(称为关键点)用格子连接起来,取(i,j)的费用就是a[i,j] 求K点全部连通的最小花费以 ...

  8. hdu4085 Peach Blossom Spring 斯坦纳树,状态dp

    (1)集合中元素表示(1<<i), i从0开始 (2)注意dp[i][ss] = min(dp[i][ss], dp[i][rr | s[i]] + dp[i][(ss ^ rr) | s ...

  9. HDU 3311 Dig The Wells(斯坦纳树)

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=3311 [题意] 给定k座庙,n个其他点,m条边,点权代表挖井费用,边权代表连边费用,问使得k座庙里 ...

随机推荐

  1. 2019-10-17 李宗盛 spss作业

    开放数据库连接是为解决异构数据库之间的数据共享而产生的,现已成为Wosa cwindows开放系统体系结构主要部分和基于Windows环境的一种数据库访问接口标准ODBS被异构数据库访问提供统一接口, ...

  2. 【ARM-Linux开发】"libxml/parser.h: 没有那个文件或目录"解决方案

    这是因为在ubuntu上没有安装libxml2-dev,这个包应该是开发用的,而已安装的libxml2应该只是像jre一样的部件. 解决方案:sudo apt-get install libxml2- ...

  3. 能力不足的C++开发会欺辱能力不足C#开发

    能力不足的C++开发会欺辱能力不足C#开发 我被C++开发欺辱的岁月   前言 人被压迫了,为什么不斗争?——鲁迅 作为一个C#开发者,我经历了,也见证了很多同行饱受C++开发的歧视和欺辱. 而且,这 ...

  4. vue加载优化方案

    我们的项目随着组件的加入,首次加载的js文件越来越大,用户等待时间越来越长:之前想着使用webpack的splitCoding来解决,看了webpack的官方文档可以配置optimization的 m ...

  5. 深度学习-LeCun、Bengio和Hinton的联合综述

    深度学习其实要入门也很简单,不要被深度学习.卷积神经网络CNN.循环神经网络RNN等某些“高大上”的专有名词所吓到或被忽悠,要相信大道至简,一个高中生只要愿意学也完全可以入门级了解并依赖一些成熟的Te ...

  6. [Cometoj#3 D]可爱的菜菜子_线段树_差分_线性基

    可爱的菜菜子 题目链接:https://cometoj.com/contest/38/problem/D?problem_id=1543 数据范围:略. 题解: 首先,如果第一个操作是单点修改,我们就 ...

  7. 【51nod】2591 最终讨伐

    [51nod]2591 最终讨伐 敲51nod是啥评测机啊,好几次都编译超时然后同一份代码莫名奇妙在众多0ms中忽然超时 这道题很简单就是\(M\)名既被诅咒也有石头的人,要么就把石头给没有石头被诅咒 ...

  8. Linux IO模式以及select poll epoll详解

    一 背景 同步IO和异步IO,阻塞IO和非阻塞IO分别是什么,到底有什么区别?不同的人在不同的上下文下给出的答案是不同的.所以先限定一下本文的上下文. 本文讨论的背景是Linux环境下的network ...

  9. 关于JS原型以及原型链、instanceof的一些理解

    一.JS原型 首先要区分两个概念 1.构造函数 2.实例:由构造函数通过new方式创建出来的就是实例 <script> function Foo() { } var f = new Foo ...

  10. spring cloud链路追踪组件sleuth和zipkin

    spring cloud链路追踪组件sleuth     主要作用就是日志埋点 操作方法 1.增加依赖             <dependency>      <groupId& ...