【BZOJ4774】修路 [斯坦纳树]
修路
Time Limit: 20 Sec Memory Limit: 256 MB
Description

Input

Output
仅一行一个整数表示答案。
Sample Input
5 5 2
1 3 4
3 5 2
2 3 1
3 4 4
2 4 3
Sample Output
9
HINT

Main idea
给定若干对点,选择若干边,询问满足每对点都连通的最小代价。
Solution
发现 d 非常小,所以我们显然可以使用斯坦纳树来求解。
斯坦纳树是用来解决这种问题的:给定若干关键点,求使得关键点连通的最小代价。
我们可以令 f[i][opt] 表示以 i 为根时,关键点连通态为opt的最小代价。(以二进制表示是否连通)
然后我们就可以用两种方法来更新 f[i][opt]:
1. 设定集合x,y,x∪y=opt且x∩y=∅,那么我们显然就可以将用x,y合并来更新opt,
2. 若 f[j][opt] 中opt = f[i][opt]中opt,那么我们就可以以连边方式合并两个集合,这种合并方式显然可以用最短路实现,使得答案更优。
然后我们就可以求出所有状态的f[i][opt],接下来再利用DP,求解。
定义Ans[opt]表示连通态为opt时最小代价,如果对应点同时连通或不连通则可以更新,枚举所有情况就可以求出答案了。
Code
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
using namespace std; const int ONE = ;
const int MOD = 1e9+; int n,m,d;
int x,y,z;
int a[ONE];
int next[ONE],first[ONE],go[ONE],w[ONE],tot;
int All,f[ONE/][],INF;
int q[],vis[ONE],tou,wei;
int Ans[]; int get()
{
int res=,Q=; char c;
while( (c=getchar())< || c>)
if(c=='-')Q=-;
if(Q) res=c-;
while((c=getchar())>= && c<=)
res=res*+c-;
return res*Q;
} void Add(int u,int v,int z)
{
next[++tot]=first[u]; first[u]=tot; go[tot]=v; w[tot]=z;
next[++tot]=first[v]; first[v]=tot; go[tot]=u; w[tot]=z;
} namespace Steiner
{
void pre()
{
memset(f,,sizeof(f)); INF=f[][];
int num = ;
for(int i=;i<=d;i++) f[i][<<num] = , num++;
for(int i=n-d+;i<=n;i++) f[i][<<num] = , num++;
All = (<<num) - ;
} void Spfa(int opt)
{
while(tou<wei)
{
int u=q[++tou];
for(int e=first[u];e;e=next[e])
{
int v=go[e];
if(f[v][opt] > f[u][opt] + w[e])
{
f[v][opt] = f[u][opt] + w[e];
if(!vis[v])
{
vis[v] = ;
q[++wei] = v;
}
}
}
vis[u] = ;
}
} void Deal()
{
for(int opt=;opt<=All;opt++)
{
for(int i=;i<=n;i++)
{
for(int sub=opt;sub;sub=(sub-) & opt)
f[i][opt] = min(f[i][opt],f[i][sub]+f[i][opt^sub]);
if(f[i][opt] != INF)
{
q[++wei] = i;
vis[i] = ;
}
}
Spfa(opt);
}
}
} bool Check(int opt)
{
for(int i=,j=(d<<)-; i<d; i++,j--)
if( ((opt & (<<i))== ) != ((opt & (<<j))==) )
return ;
return ;
} int main()
{
n=get(); m=get(); d=get();
for(int i=;i<=m;i++)
{
x=get(); y=get(); z=get();
Add(x,y,z);
} Steiner::pre();
Steiner::Deal(); memset(Ans,,sizeof(Ans));
for(int opt=;opt<=All;opt++)
if(Check(opt))
{
for(int i=;i<=n;i++)
Ans[opt] = min(Ans[opt], f[i][opt]);
} for(int opt=;opt<=All;opt++)
for(int sub=opt;sub;sub=(sub-) & opt)
Ans[opt] = min(Ans[opt], Ans[sub]+Ans[opt^sub]); if(Ans[All] == INF) printf("-1");
else printf("%d",Ans[All]);
}
【BZOJ4774】修路 [斯坦纳树]的更多相关文章
- 「长乐集训 2017 Day8」修路 (斯坦纳树)
题目描述 村子间的小路年久失修,为了保障村子之间的往来,AAA君决定带领大家修路. 村子可以看做是一个边带权的无向图GGG, GGG 由 nnn 个点与 mmm 条边组成,图中的点从 1∼n1 \si ...
- 【BZOJ4774】修路(动态规划,斯坦纳树)
[BZOJ4774]修路(动态规划,斯坦纳树) 题面 BZOJ 题解 先讲怎么求解最小斯坦纳树. 先明白什么是斯坦纳树. 斯坦纳树可以认为是最小生成树的一般情况.最小生成树是把所有给定点都要加入到联通 ...
- 【BZOJ4774/4006】修路/[JLOI2015]管道连接 斯坦纳树
[BZOJ4774]修路 Description 村子间的小路年久失修,为了保障村子之间的往来,法珞决定带领大家修路.对于边带权的无向图 G = (V, E),请选择一些边,使得1 <= i & ...
- 初涉斯坦纳树&&bzoj4774: 修路
斯坦纳树的基础应用 斯坦纳树有什么用 个人一点粗浅理解…… 最基本形式的斯坦纳树问题(以下简称母问题):给定图G和一个关键点集V.求在G中选取一个权值最小(这里权值可以有很多变式)的边集E使V中的点两 ...
- 【BZOJ2595】游览计划(状压DP,斯坦纳树)
题意:见题面(我发现自己真是越来越懒了) 有N*M的矩阵,每个格子有一个值a[i,j] 现要求将其中的K个点(称为关键点)用格子连接起来,取(i,j)的费用就是a[i,j] 求K点全部连通的最小花费以 ...
- HDU 4085 斯坦纳树
题目大意: 给定无向图,让前k个点都能到达后k个点(保护地)中的一个,而且前k个点每个需要占据后k个中的一个,相互不冲突 找到实现这个条件达到的选择边的最小总权值 这里很容易看出,最后选到的边不保证整 ...
- 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 ...
- hdu 3311 斯坦纳树
思路:虚拟一个0号节点,将每个点建一条到0号节点的边,权值为挖井需要的价值.并要保证0号节点同另外n个寺庙一样被选择即可. 然后就是求斯坦纳树了. #include<map> #inclu ...
- HDU 3311 Dig The Wells(斯坦纳树)
[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=3311 [题意] 给定k座庙,n个其他点,m条边,点权代表挖井费用,边权代表连边费用,问使得k座庙里 ...
随机推荐
- PHP批量替换MySql数据库中的数据内容
<?php //替换数据库内容类 class replace{ public $dbAddress; //数据库地址 public $dbUser; //数据库用户名 public $dbPwd ...
- EF报错“EntityValidationErrors”
在使用EF更新实体的时候报错,显示界面如下: 点击查看详情: 在查看详细的窗体中,EntityValidationErrors里面的也看不到具体的错误原因.在网上 ...
- AutoMapper.RegExtension 介绍
AutoMapper.RegExtension 为一个特小特小特小的用来根据约定自动调用AutoMapper中的方法配置映射的扩展库.你可以引入该库也可以将源码中核心部分的代码文件夹整个拷贝至项目中. ...
- Ubuntu下使用Git_4
在这个第四个文章中,我将练习GIT的高级阶段了,由于高级阶段的内容转的比较多,我自己的代码除了我自己可以看懂意外,大家可能看不懂,所以我将会按照 http://git.wiki.navisec.it/ ...
- 虚拟现实-VR-UE4-创建第一个C++项目——Hello word
这部分主要是调用在C++中用代码实现在游戏界面上面输出一行文字 第一步,新建C++版本的工程文件,在4.12版本以后,在创建后,都会自动打开Vs编译器. 如下图 在VS中点击编译,等带编译,第一次等待 ...
- deepin linux 安装/启动jeakins报错:处理
ERROR: No Java executable found in current PATH: /bin:/usr/bin:/sbin:/usr/sbin 安装报错: 1.如还未安装java,则安装 ...
- day-9 sklearn库和python自带库实现最近邻KNN算法
K最近邻(k-Nearest Neighbor,KNN)分类算法,是一个理论上比较成熟的方法,也是最简单的机器学习算法之一.该方法的思路是:如果一个样本在特征空间中的k个最相似(即特征空间中最邻近)的 ...
- html5实现web app摇一摇换歌
微信可以摇歌曲,根据声音识别出歌曲,然后返回歌曲信息,利用html5的deviceOrientation特性和deviceMotion事件也可以在web app上实现类似于微信摇一摇的功能,原生的ap ...
- 好用的在线pdf转化器
https://smallpdf.com/cn/compress-pdf
- input只改变光标的颜色 不改变字的颜色
color: red; text-shadow: 0px 0px 0px #000; -webkit-text-fill-color: transparent;把这些放到input里文字通过阴影实现 ...