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] - ]);
}
}

最新文章

  1. SSH框架简化
  2. vmstat和iostat
  3. 让Redis在你的系统中发挥更大作用的几点建议
  4. 如何在Kali Linux中搭建钓鱼热点
  5. Spring 常用注解
  6. 转!!java线程状态
  7. backup site collection
  8. HBase笔记--filter的使用
  9. Gson 基础教程 —— 自定义类型适配器(TypeAdapter)
  10. Codeforces 484A - Bits 二进制找1
  11. if语句2017-03-17
  12. 《尚学堂_史上最易懂的设计模式视频》--章节5 动态代理-JDK6自带的编译器
  13. 最优装载—dp
  14. springboot Cacheable(redis),解决key乱码问题
  15. java第一章抽象和封装
  16. 华硕X99-A II 安装使用 志强 XEON E5-1603 v4
  17. shiro-redis实现session存储到redis
  18. 用ajax传递json,返回前台的中文乱码问题
  19. java Date型时间比较大小
  20. 最常使用Eclipse快捷键

热门文章

  1. nrpe command
  2. 递归-PrintDigit
  3. fastjson带泛型反序列化的用法
  4. 【DSP开发】DSP COFF 与 ELF文件
  5. C#实现多线程的方式:Task——任务
  6. 在centos 7下升级内核
  7. leveldb单元测试之宏定义源码剖析
  8. JS对字符串的操作,截取
  9. 【AtCoder】AGC001
  10. 常见的几种web攻击