【BZOJ4774】修路(动态规划,斯坦纳树)
【BZOJ4774】修路(动态规划,斯坦纳树)
题面
题解
先讲怎么求解最小斯坦纳树。
先明白什么是斯坦纳树。
斯坦纳树可以认为是最小生成树的一般情况。最小生成树是把所有给定点都要加入到联通块中。而斯坦纳树不一样,斯坦纳树只需要把指定点集中的所有点全部加入到联通块中,并且允许使用点集以外的点。
然而求解最小斯坦纳树是一个\(NP\)问题,所以只能状压解决。
设\(f[S][i]\)表示指定点的联通情况为\(S\),并且当且的斯坦纳树以\(i\)为根,\(i\)可以是图上任意一个点。
考虑如何转移:
\(f[S][i]\rightarrow f[T][i]+f[S\oplus T][i],S\&T=0\)
这个转移的含义是,你以当前点为根的斯坦纳树,可以拆分为两个以当前点为根的斯坦纳树。
另外一个转移是换根:
\(f[S][i]\rightarrow f[S][j]+e[i][j]\),其中\(e[i][j]\)是链接\(i,j\)的边的边长。
这一步你可以认为一开始没有联通\(j\),现在我们换根,所以要把它给添加进来。
但是发现第二个转移具有后效性,所以写成\(SPFA\)的形式。
接着考虑怎么求解本题的问题,也就是最小斯坦纳森林。
设\(g[S]\)表示联通了点集\(S\)的最小斯坦纳森林。
那么,如果\(S\)中要求在一个联通块的点全部都连在了一起,那么显然它可以和一个无交集,并且同时满足要求连接在一起的点都连在一起的话,这两个集合显然可以取并集转移。
即\(g[S]=g[T]+g[S\oplus T]\),条件是\(T\)和\(S\oplus T\)这两个集合中如果包含了某个点,就必定包含要求连接在一起的点。
这样子就做完了。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define MAX 10100
inline int read()
{
int x=0;bool t=false;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=true,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return t?-x:x;
}
int n,m,D;
struct Line{int v,next,w;}e[MAX<<1];
int h[MAX],cnt=1;
inline void Add(int u,int v,int w){e[cnt]=(Line){v,h[u],w};h[u]=cnt++;}
int f[1<<8][MAX],g[1<<8];
bool vis[MAX];
queue<int> Q;
void SPFA(int *f)
{
while(!Q.empty())
{
int u=Q.front();Q.pop();
for(int i=h[u];i;i=e[i].next)
if(f[e[i].v]>f[u]+e[i].w)
{
f[e[i].v]=f[u]+e[i].w;
if(!vis[e[i].v])Q.push(e[i].v),vis[e[i].v]=true;
}
vis[u]=false;
}
}
bool check(int s){return (s&((1<<D)-1))==(s>>D);}
int main()
{
n=read();m=read();D=read();
for(int i=1;i<=m;++i)
{
int u=read(),v=read(),w=read();
Add(u,v,w);Add(v,u,w);
}
memset(f,63,sizeof(f));memset(g,63,sizeof(g));
for(int i=1;i<=D;++i)f[1<<(i-1)][i]=f[1<<(D+i-1)][n-i+1]=0;
int S=1<<(D<<1);
for(int i=0;i<S;++i)
{
for(int j=1;j<=n;++j)
{
for(int k=i&(i-1);k;k=(k-1)&i)
f[i][j]=min(f[i][j],f[k][j]+f[i^k][j]);
if(f[i][j]<=1e9)Q.push(j),vis[j]=true;
}
SPFA(f[i]);
for(int j=1;j<=n;++j)g[i]=min(g[i],f[i][j]);
}
for(int i=0;i<S;++i)
for(int t=(i-1)&i;t;t=(t-1)&i)
if(check(t)&&check(i^t))
g[i]=min(g[i],g[t]+g[i^t]);
printf("%d\n",g[S-1]<=1e9?g[S-1]:-1);
return 0;
}
【BZOJ4774】修路(动态规划,斯坦纳树)的更多相关文章
- 【BZOJ4774/4006】修路/[JLOI2015]管道连接 斯坦纳树
[BZOJ4774]修路 Description 村子间的小路年久失修,为了保障村子之间的往来,法珞决定带领大家修路.对于边带权的无向图 G = (V, E),请选择一些边,使得1 <= i & ...
- 初涉斯坦纳树&&bzoj4774: 修路
斯坦纳树的基础应用 斯坦纳树有什么用 个人一点粗浅理解…… 最基本形式的斯坦纳树问题(以下简称母问题):给定图G和一个关键点集V.求在G中选取一个权值最小(这里权值可以有很多变式)的边集E使V中的点两 ...
- 【BZOJ4774】修路 [斯坦纳树]
修路 Time Limit: 20 Sec Memory Limit: 256 MB Description Input Output 仅一行一个整数表示答案. Sample Input 5 5 2 ...
- 「长乐集训 2017 Day8」修路 (斯坦纳树)
题目描述 村子间的小路年久失修,为了保障村子之间的往来,AAA君决定带领大家修路. 村子可以看做是一个边带权的无向图GGG, GGG 由 nnn 个点与 mmm 条边组成,图中的点从 1∼n1 \si ...
- 【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座庙里 ...
随机推荐
- selenium 基本常用操作
from selenium import webdriverfrom selenium.webdriver.common.action_chains import ActionChains #鼠标操作 ...
- 1.VBA 基本概念——《Excel VBA 程序开发自学宝典》
1.1 常见对象及含义 对象名 含义 application 整个Excel应用程序 window 窗口 worksheet 一个工作表 sheets 指定工作簿的所有工作表的合集 shaperan ...
- hostname命令详解
基础命令学习目录首页 原文链接:https://idc.wanyunshuju.com/cym/68.html Linux操作系统的hostname是一个kernel变量,可以通过hostname命令 ...
- 精通Python爬虫-03-狩猎大师
声明: 本系列文章原创于慕课网,作者秋名山车神,任何人不得以任何形式在不经作者允许的情况下,进行任何形式的印刷以及销售,转载需注明出处及此声明. 本系列文章更新至少每周一更,将涉及Python爬虫基础 ...
- java分布式事务,及解决方案
1.什么是分布式事务 分布式事务就是指事务的参与者.支持事务的服务器.资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上.以上是百度百科的解释,简单的说,就是一次大的操作由不同的小操作组成 ...
- IOS上z-index和fixed定位无效
IOS上z-index和fixed定位无效 在该元素上加: -webkit-transform:translateZ(1px); -moz-transform:translateZ(1px); -o- ...
- 团队作业 & alpha最终测试报告
本次ALPHA版本测试是依据Daily Scrum11.16(http://www.cnblogs.com/newbe/p/4101339.html)分配的任务有序进行的,从11.16~11.23.为 ...
- Linux 环境下Web环境搭建————ActiveMQ
1.下载安装包http://activemq.apache.org/activemq-5143-release.html 2.解压至指定目录 bin目录下为执行脚本 (脚本无法执行需要修改权限(chm ...
- Go going软件NABCD
N (Need 需求):gogoing项目目前打算做得是一个基于石家庄铁道大学在校大学生对于短期节假日出行旅游的指南.次关键的定义为“简单”.“简单”则体现在我们的软件使用简单.方便,以及界面的简洁 ...
- Leetcode题库——24.两两交换链表中的节点
@author: ZZQ @software: PyCharm @file: swapPairs.py @time: 2018/10/20 19:49 说明:给定一个链表,两两交换其中相邻的节点,并返 ...