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. Storm拓扑的并行度(parallelism)介绍

    Storm拓扑的并行度(parallelism)介绍 1.Storm分为3个主要实体,用于在Storm集群中运行拓扑        工作进程:Worker Process,也称为Worker      ...

  2. delphi算法

    /  求余 mod 取模 var a1,a2,a3 : Integer; b1,b2,b3 : Integer; c1,c2 : Integer;begin a1 := 987; //ShowMess ...

  3. MarkWord - 可发布博客的 Markdown编辑器 代码开源

    因为前一段时间看到 NetAnalyzer 在Windows10系统下UI表现惨不忍睹,所以利用一段时间为了学习一下WPF相关的内容,于是停停写写,用了WPF相关的技术,两个星期做了一个Markdow ...

  4. 一款豪华绚丽的移动端图册(zepto.js+photoswipe.js)

    应公司要求,开发一款移动端杂志(等同于移动端幻灯片相册,iOS上能轻松滑动缩放,android上也能滑动缩放).网上找了很久没有符合需求的插件,无意间找到了photoswipe,进行改造之后就成了符合 ...

  5. windows 7 SDK和DDK下载地址

    查个小资料,得到地址,顺便记录一下. Windows Driver Kit Version 7.1.0 http://www.microsoft.com/downloads/details.aspx? ...

  6. 程序员实用的 MySQL sql 语句

    这儿只讲究实用,  程序员编程时常用到的 MySQL的 sql语句(不包括基本的 select, update, delete 等语句). 1. 添加一个用户build,并赋予所有权限的命令 gran ...

  7. Java JDBC连接SQL Server2005错误:通过port 1433 连接到主机 localhost 的 TCP/IP 连接失败

    错误原因例如以下: Exception in thread "main" org.hibernate.exception.JDBCConnectionException: Cann ...

  8. android高仿微信UI点击头像显示大图片效果

    用过微信的朋友朋友都见过微信中点击对方头像显示会加载大图,先贴两张图片说明下: 这种UI效果对用户的体验不错,今天突然有了灵感,试着去实现,结果就出来了.. 下面说说我的思路: 1.点击图片时跳转到另 ...

  9. window成员和document成员

    输出浏览器成员和DOM成员(以下为safari浏览器测试)(浏览器不同对象成员有差异) window成员 <script type="text/javascript"> ...

  10. 【转】在写一个iOS应用之前必须做的7件事(附相关资源)

    转自:http://www.cocoachina.com/ios/20160316/15687.html 本文由CocoaChina--不再犹豫(tao200610704@126.com)翻译 作者: ...