题目链接

题目大意:有一张无向图,每条边有一定的花费,给出一些点集,让你从中选出一些边,用最小的花费将每个点集内的点相互连通,可以使用点集之外的点(如果需要的话)。

算是斯坦纳树的入门题吧。

什么是斯坦纳树呢?

假定有这样的题目:给你一张无向图和一个点集,每条边有一定的花费,让你选出一些边使点集内的所有点连通,求最小花费。

可以发现,如果点集大小为2,那么就转化成了一个两点间最短路问题。

而如果点集大小为总点数,那么就转化成了一个最小生成树问题。

进一步可以推出,如果点集大小为3,那么答案就相当于选出一个点,使该点到点集内三点的距离之和最短。

那么如果点集大小为4,5,...,乃至更多,怎么办?

随着点集的增加,情况也会越来越复杂,好像一时难以找到突破点。

其实这类题有着通用的解法,也就是斯坦纳树的dp。

设$dp[S][i]$为构造出以i为根(选根只是为了方便转移,无实际意义,相当于无根树转有根树),连通的点集为S的树的最小化费,则初始状态为$dp[1<<i][i]=0$,且存在两类转移:

$dp[S][i]=\left\{\begin{matrix}\begin{aligned}&min\{dp[S'][i]+dp[S\oplus S'][i]\}\\&min\{dp[S][j]+d[j][i]\}\end{aligned}\end{matrix}\right.$

其中$S'$是$S$的子集,$d[j][i]$表示点j与点i直接相连的边的花费。

其中第一类转移是有序的,可以直接dp求解;而第二类是无序的,需要用SPFA求解(用Dijkstra理论上也可以,但通常SPFA更快)

这样的转移还存在一个问题,就是有些边可能会重复经过,但总会存在一个不会重复的最优解,所以可以忽略掉这个问题。

这是只有一个点集时的情况,如果有多个点集的话只需要再加一个转移就好了:

$mi[S]=min\{mi[S']+mi[S\oplus S']\}$

其中$mi[S]$表示将点集S连通的最小花费,初始值为$mi[S]=min\{dp[S][i]\}$,且$S$和$S\oplus S'$都要满足:对于任意一个点集中的点,要么不包含,要么全部包含。

复杂度$O(n(3^k+Am2^k))$,A为SPFA的常数,一般较小。

 #include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=+,inf=0x3f3f3f3f;
int n,m,k,hd[N],ne,inq[N],dp[<<][N],mi[<<],SS[+],Y[N],X[N],ok[<<];
struct E {int v,c,nxt;} e[N*];
void addedge(int u,int v,int c) {e[ne]= {v,c,hd[u]},hd[u]=ne++;}
queue<int> q;
void upd(int u,int c,int S) {
if(dp[S][u]>c) {dp[S][u]=c; if(!inq[u])inq[u]=,q.push(u);}
}
void spfa(int S) {
while(q.size())q.pop();
memset(inq,,sizeof inq);
for(int i=; i<=n; ++i)if(dp[S][i]!=inf)q.push(i),inq[i]=;
while(q.size()) {
int u=q.front();
q.pop(),inq[u]=;
for(int i=hd[u]; ~i; i=e[i].nxt)upd(e[i].v,dp[S][u]+e[i].c,S);
}
}
int main() {
memset(hd,-,sizeof hd),ne=;
scanf("%d%d%d",&n,&m,&k);
while(m--) {
int u,v,c;
scanf("%d%d%d",&u,&v,&c);
addedge(u,v,c);
addedge(v,u,c);
}
for(int i=; i<k; ++i) {
int a,b;
scanf("%d%d",&a,&b);
Y[b]=i,X[i]=b;
SS[a]|=<<i;
}
for(int i=; i<=; ++i)if(SS[i])ok[SS[i]]=;
for(int i=; i<=n; ++i)spfa(i);
memset(dp,inf,sizeof dp);
for(int i=; i<k; ++i)dp[<<i][X[i]]=;
for(int S=; S<(<<k); ++S) {
for(int S2=(S-)&S; S2; S2=(S2-)&S)
for(int i=; i<=n; ++i)
dp[S][i]=min(dp[S][i],dp[S2][i]+dp[S^S2][i]);
spfa(S);
mi[S]=inf;
for(int i=; i<=n; ++i)mi[S]=min(mi[S],dp[S][i]);
}
for(int S=; S<(<<k); ++S)
for(int S2=(S-)&S; S2; S2=(S2-)&S)if(ok[S2]&&ok[S^S2])
mi[S]=min(mi[S],mi[S2]+mi[S^S2]),ok[S]=;
printf("%d\n",mi[(<<k)-]);
return ;
}

洛谷P3264 [JLOI2015]管道连接 (斯坦纳树)的更多相关文章

  1. BZOJ 4006 Luogu P3264 [JLOI2015]管道连接 (斯坦纳树、状压DP)

    题目链接: (bzoj)https://www.lydsy.com/JudgeOnline/problem.php?id=4006 (luogu)https://www.luogu.org/probl ...

  2. 洛谷P3264 [JLOI2015]管道连接(斯坦纳树)

    传送门 感觉对斯坦纳树还是有很多疑惑啊…… 等到时候noip没有爆零的话再回来填坑好了 //minamoto #include<iostream> #include<cstdio&g ...

  3. BZOJ4006 JLOI2015 管道连接(斯坦纳树生成森林)

    4006: [JLOI2015]管道连接 Time Limit: 30 Sec Memory Limit: 128 MB Description 小铭铭最近进入了某情报部门,该部门正在被如何建立安全的 ...

  4. BZOJ4006: [JLOI2015]管道连接(斯坦纳树,状压DP)

    Time Limit: 30 Sec  Memory Limit: 128 MBSubmit: 1171  Solved: 639[Submit][Status][Discuss] Descripti ...

  5. 【bzoj4006】[JLOI2015]管道连接 斯坦纳树+状压dp

    题目描述 给出一张 $n$ 个点 $m$ 条边的无向图和 $p$ 个特殊点,每个特殊点有一个颜色.要求选出若干条边,使得颜色相同的特殊点在同一个连通块内.输出最小边权和. 输入 第一行包含三个整数 n ...

  6. 【BZOJ4774/4006】修路/[JLOI2015]管道连接 斯坦纳树

    [BZOJ4774]修路 Description 村子间的小路年久失修,为了保障村子之间的往来,法珞决定带领大家修路.对于边带权的无向图 G = (V, E),请选择一些边,使得1 <= i & ...

  7. bzoj 4006 [JLOI2015]管道连接——斯坦纳树

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4006 除了模板,就是记录 ans[ s ] 表示 s 合法的最小代价.合法即保证 s 里同一 ...

  8. 洛谷 P7450 - [THUSCH2017] 巧克力(斯坦纳树+随机化)

    洛谷题面传送门 9.13 补之前 8.23 做的题,不愧是鸽子 tzc( 首先我们先来探讨一下如果 \(c_{i,j}\le k\) 怎么做,先考虑第一问.显然一个连通块符合条件当且仅当它能够包含所有 ...

  9. bzoj 4006 管道连接 —— 斯坦纳树+状压DP

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4006 用斯坦纳树求出所有关键点的各种连通情况的代价,把这个作为状压(压的是集合选择情况)的初 ...

随机推荐

  1. 阿里RDS

    白名单设置: 创建高权限帐号:

  2. poj1905 Expanding Rods(二分)

    题目链接:https://vjudge.net/problem/POJ-1905 题意:有一根长len的木棍,加热了n度,长度会膨胀为len*(1+n*c),c为膨胀系数.现在把这根木棍夹在两堵墙之间 ...

  3. iis实现方向代理

    将请求的网址重写重定向到其它网址.当80端口被占用无法同时使用两个Web服务的解决方案,使得IIS和Apache Tomcat 共存 0|1环境 WindowServer 2008 IIS7 Apac ...

  4. ABP领域层定义仓储并实现

    原文作者:圣杰 原文地址:ABP入门系列(3)——领域层定义仓储并实现 在原文作者上进行改正,适配ABP新版本.内容相同 一.先来介绍下仓储 仓储(Repository): 仓储用来操作数据库进行数据 ...

  5. table表格整体居中 和 table表格中各行各列内容居中

    1.table表格整个居中<div style="text-align: center;"> <table border="1" style= ...

  6. T100——修改单身栏位,开窗,当前行

    PRIVATE FUNCTION axmt500_update_xmdc028() ###更改出货库位 DEFINE l_i INT DEFINE l_index INT DIALOG ATTRIBU ...

  7. 搭建kafka集群

    1:确认zookeeper集群安装正确,防火墙关闭 2:下载kafka安装文件 cd /usr/local/mydown wget http://mirror.bit.edu.cn/apache/ka ...

  8. lua与c的交互(运用)

    (1)lua程序 (2)C++程序(头文件) extern "C" {     #include "lua.h"     #include "lual ...

  9. O039、Unshelve Instance 操作详解

    参考https://www.cnblogs.com/CloudMan6/p/5529915.html   上一节我们 shelve Instance 到 Glance,本节学习如何通过 unshelv ...

  10. 爱上Java诊断利器之Arthas

    1. Arthas是什么? 摘自Arthas的Github介绍: Arthas is a Java Diagnostic tool open sourced by Alibaba. Arthas al ...