http://acm.hdu.edu.cn/showproblem.php?pid=4085

斯坦纳树。

用状压DP。

一共有2K个关键点:1,2...,K和N-K+1,N-K+2...,N,我们用一个2K位二进制数表示是否包含这些关键点。

F[i][state]表示一定包含i点,至少包含关键点state的生成树的最小费用,其中state是一个二进制数。

有2个转移:

F[i][state]=min{F[i][s]+F[i][state-s]}(其中s是state的子集)

F[i][state]=min{F[j][state]+cost}(其中i号点和j号点有边相连,费用为cost)

我们按state划分阶段,相同的state做SPFA。

现在我们已经求出F了。

记DP[state]表示至少包含关键点state时的生成树的最小费用,其实就是DP[state]=min{F[i][state]}(1<=i<=N)

我们还要判断state是否合法,就是人的个数和房子的个数相等,否则生成树就是不合法的。

但是现在DP[state]表示的还只是一颗生成树。

答案可以是森林。

我们可以从state的子集更新:DP[state]=min{DP[state],DP[s]+DP[state-s]}(其中s是state的子集)

这样就变成了森林了。

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<fstream>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<utility>
#include<set>
#include<bitset>
#include<vector>
#include<functional>
#include<deque>
#include<cctype>
#include<climits>
#include<complex>
//#include<bits/stdc++.h>适用于CF,UOJ,但不适用于poj using namespace std; typedef long long LL;
typedef double DB;
typedef pair<int,int> PII;
typedef complex<DB> CP; #define mmst(a,v) memset(a,v,sizeof(a))
#define mmcy(a,b) memcpy(a,b,sizeof(a))
#define fill(a,l,r,v) fill(a+l,a+r+1,v)
#define re(i,a,b) for(i=(a);i<=(b);i++)
#define red(i,a,b) for(i=(a);i>=(b);i--)
#define ire(i,x) for(typedef(x.begin()) i=x.begin();i!=x.end();i++)
#define fi first
#define se second
#define m_p(a,b) make_pair(a,b)
#define p_b(a) push_back(a)
#define SF scanf
#define PF printf
#define two(k) (1<<(k)) template<class T>inline T sqr(T x){return x*x;}
template<class T>inline void upmin(T &t,T tmp){if(t>tmp)t=tmp;}
template<class T>inline void upmax(T &t,T tmp){if(t<tmp)t=tmp;} const DB EPS=1e-;
inline int sgn(DB x){if(abs(x)<EPS)return ;return(x>)?:-;}
const DB Pi=acos(-1.0); inline int gint()
{
int res=;bool neg=;char z;
for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
if(z==EOF)return ;
if(z=='-'){neg=;z=getchar();}
for(;z!=EOF && isdigit(z);res=res*+z-'',z=getchar());
return (neg)?-res:res;
}
inline LL gll()
{
LL res=;bool neg=;char z;
for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
if(z==EOF)return ;
if(z=='-'){neg=;z=getchar();}
for(;z!=EOF && isdigit(z);res=res*+z-'',z=getchar());
return (neg)?-res:res;
} const int maxN=;
const int maxM=;
const int maxK=;
const int INF=0x3f3f3f3f; int N,M,K;
int bit[*maxK+];
int F[maxN+][two(*maxK)+];
int vis[maxN+][two(*maxK)+]; int now,first[maxN+];
struct Tedge{int v,cost,next;}edge[*maxM+]; inline void addedge(int u,int v,int cost)
{
now++;
edge[now].v=v;
edge[now].cost=cost;
edge[now].next=first[u];
first[u]=now;
} queue<PII>Q;
inline void SPFA()
{
while(!Q.empty())
{
int u=Q.front().fi,state=Q.front().se,i,v,cost;Q.pop();
vis[u][state]=;
for(i=first[u],v=edge[i].v,cost=edge[i].cost;i!=-;i=edge[i].next,v=edge[i].v,cost=edge[i].cost)
if(F[v][state]>F[u][state]+cost)
{
F[v][state]=F[u][state]+cost;
if(!vis[v][state])Q.push(PII(v,state)),vis[v][state]=;
}
}
} #define wei(v,k) ((v>>((k)-1))&1)
inline int check(int s)
{
int i,res=;
re(i,K+,*K)if(wei(s,i))res++;
re(i,,K)if(wei(s,i))res--;
return res==;
} int DP[two(*maxK)+]; int main()
{
freopen("hdu4085.in","r",stdin);
freopen("hdu4085.out","w",stdout);
int i,j;
for(int Case=gint();Case;Case--)
{
N=gint();M=gint();K=gint();
mmst(first,-);now=-;
re(i,,M){int u=gint(),v=gint(),cost=gint();addedge(u,v,cost);addedge(v,u,cost);}
mmst(F,0x3f);
mmst(bit,);
re(i,,K)bit[i]=two(i-),F[i][bit[i]]=;
re(i,,K)bit[N-K+i]=two(K+i-),F[N-K+i][bit[N-K+i]]=;
int state,maxstate=two(*K)-;
re(state,,maxstate)
{
re(i,,N)
{
for(int s=(state-)&state;s;s=(s-)&state)
upmin(F[i][state],F[i][s]+F[i][state-s]);
if(F[i][state]!=INF)Q.push(PII(i,state)),vis[i][state]=;
}
SPFA();
}
mmst(DP,0x3f);
re(state,,maxstate)re(i,,N)upmin(DP[state],F[i][state]);
re(i,,maxstate)if(check(i))
for(j=(i-)&i;j;j=(j-)&i)if(check(j))
upmin(DP[i],DP[j]+DP[i-j]);
if(DP[maxstate]==INF) PF("No solution\n"); else PF("%d\n",DP[maxstate]);
}
return ;
}

hdu4085的更多相关文章

  1. 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 ...

  2. hdu4085 Peach Blossom Spring

    Peach Blossom Spring http://acm.hdu.edu.cn/showproblem.php?pid=4085 Time Limit: 10000/5000 MS (Java/ ...

  3. hdu4085(斯坦纳树)

    题意: 给你n,m,k ,分别表示有n个点,m条边,每条边有一个权值,表示修复这条边需要的代价,从前k个点中任取一个使其和后k个点中的某一个点,通过边连接,并且必须是一一对应,问最小的代价是多少. 分 ...

  4. Minimal Steiner Tree ACM

    上图论课的时候无意之间看到了这个,然后花了几天的时间学习了下,接下来做一个总结. 一般斯坦纳树问题是指(来自百度百科): 斯坦纳树问题是组合优化问题,与最小生成树相似,是最短网络的一种.最小生成树是在 ...

  5. HDU 4085 斯坦纳树+DP

    https://cn.vjudge.net/problem/HDU-4085 给你n,m,k ,分别表示有n个点,m条边,每条边有一个权值,表示修复这条边需要的代价 从前k个点中任取一个使其和后k个点 ...

随机推荐

  1. Shell脚本常用命令简介

    格式化日期yyyy-mm-dd hh:mm:ss显示 date "+%Y-%m-%d %H:%M:%S" 将内容写入到新文件 echo "hello">a ...

  2. 迭代导出word 文档

    Map迭代的使用: Map map = new HashMap() ; Iterator it = map.entrySet().iterator() ; while (it.hasNext()) { ...

  3. MyBatis的简单操作

    这里将的是简单的增.删.改.查等基本操作 首先创建java项目,导入相应的依赖包,这里可以参考上一篇博客 1.添加数据 在jike.book.pojo包中,新建java类 JiKeUser.java: ...

  4. PHP中字符串类型与数值类型混合计算

    字符串转数值的规则 当一个字符串被当作一个数值来取值,其结果和类型如下: 如果该字符串没有包含 '.','e' 或 'E' 并且其数字值在整型的范围之内(由 PHP_INT_MAX 所定义),该字符串 ...

  5. SQL Server 启用 xp_cmdshell 与bcp 使用

    启用 xp_cmdshell 1: sp_configure 'show advanced options',1 2: reconfigure 3: GO 4: 5: sp_configure 'xp ...

  6. kvm cobbler无人值守批量安装操作系统

    kvm cobbler无人值守批量安装操作系统 cobbler:一个自动网络安装系统的工具,集成PEX.dhcp.dns.tftpd.sync等服务.可以供大家管理安装操作系统 kvm:Linux系统 ...

  7. 2.x最终照着教程,成功使用OpenGL ES 绘制纹理贴图,添加了灰度图

    在之前成功绘制变色的几何图形之后,今天利用Openg ES的可编程管线绘制出第一张纹理. 学校时候不知道OpenGL的重要性,怕晦涩的语法.没有跟老师学习OpenGL的环境配置,现在仅仅能利用coco ...

  8. (各个公司面试原题)在线做了一套CC++综合測试题,也来測一下你的水平吧(二)

    刚才把最后的10道题又看了下.也发上来吧. 以下给出试题.和我对题目的一些理解 前10道题地址 (各个公司面试原题)在线做了一套CC++综合測试题.也来測一下你的水平吧(一) 11.设已经有A,B,C ...

  9. Codeforces 220B - Little Elephant and Array 离线树状数组

    This problem can be solve in simpler O(NsqrtN) solution, but I will describe O(NlogN) one. We will s ...

  10. DELL RACADM 工具使用介绍

    如果iDRAC的IP或者设置出现问题,不能够链接,那么可以通过RACADM这个程序在系统层面可以对iDRAC进行设置,使用的方法以及命令都在下边. RACADM provides command li ...