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. puppet aix package 之rsync安装

    AIX中使用RPM安装RSync遇到的问题及解决办法 最近在折腾AIX的系统,它里面本来有一个包管理工具叫installp,但是俺不会用,也不知道从那里找包. 幸亏AIX提供了RPM的支持,所以安装软 ...

  2. (转)实战p12文件转pem文件

    需要实现这个功能的一般都是app开发证书不支持通配符(即com.xxx.xxx.xxx格式),在业务需求上类似消息推送这样的业务. 1.首先生成一个ssl的证书 选择app IDS 后实现下面这个(这 ...

  3. FilterDispatcher 的作用(struts2.1.3以前,新版本改了)

    org.apache.struts2.dispatcher.FilterDispatcher是Struts2的主要的Filter,负责四个方面的功能: (1)执行Actions (2)清除Action ...

  4. 使用 AtomicInteger 进行计数(java多线程优化)

    通常,在我们实现多线程使用的计数器或随机数生成器时,会使用锁来保护共享变量.这样做的弊端是如果锁竞争的太厉害,会损害吞吐量,因为竞争的同步非常昂贵. volatile 变量虽然可以使用比同步更低的成本 ...

  5. 经常使用ARM汇编指令

    一面学习,一面总结,一面记录. 以下是整理在网上找到的一些资料,简单整理记录一下,方便以后查阅. ARM处理器的指令集能够分为跳转指令.数据处理指令.程序状态寄存器(PSR)处理指令.载入/存储指令. ...

  6. swift 中String常用操作

    1.  字符串定义 var s = "aaaaaa" // 两个字符串均为空并等价. var emptyString = ""   var anotherEmp ...

  7. 玩转Win32开发(2):完整的开发流程

          上一篇中我给各位说了一般人认为C++中较为难的东西——指针.其实对于C++,难点当然不局限在指针这玩意儿上,还有一些有趣的概念,如模板类.虚基类.纯虚函数等,这些都是概念性的东西,几乎每一 ...

  8. Shell-WEB目录监控

    #!/bin/sh #date:2015-12-08 #filename:check_webfile.sh #作者:李兴利 #Email:1162572407@qq.com #version:v1.1 ...

  9. linux查看系统版本

       RHEL7.0以下,查看系统版本的方式: [rusky@rheltest1 ~]$ cat /proc/version Linux version -.el6.x86_64 (mockbuild ...

  10. 配置squid代理服务

    1. 简述一下squid的用途?squid可以做代理和缓存服务器,而做代理时,可以分为正向代理和反向代理.正向代理用在企业办公环境中,企业员工上网通过代理来上网,代理的缓存功能可以为企业节省宝贵的带宽 ...