斯坦纳树的基础应用

斯坦纳树有什么用

个人一点粗浅理解……

最基本形式的斯坦纳树问题(以下简称母问题):给定图G和一个关键点集V。求在G中选取一个权值最小(这里权值可以有很多变式)的边集E使V中的点两两连通。

由于这个母问题只对关键点有限制。那么可以用状压dp的做法:$f[i][j]$表示对于$i$点而言,它已连通的关键点状态为$j$的最小代价。

那么$f[i][j]$就有两种转移方式:1.从$f[i][t]$转移而来;2.从$f[v][j]$转移而来。

注意到第一种转移就相当于枚举子集;第二种转移形如最短路问题。那么只需要每次额外对于第二种转移做一遍最短路即可。

最终的时间复杂度为$O(n*3^k)$。

相关博客:

1.【bzoj5180】[Baltic2016]Cities 斯坦纳树

2.斯坦纳树 Steiner Tree

【dp套斯坦纳树】bzoj4774: 修路

Description

村子间的小路年久失修,为了保障村子之间的往来,法珞决定带领大家修路。对于边带权的无向图 G = (V, E),
请选择一些边,使得1 <= i <= d, i号节点和 n - i + 1 号节点可以通过选中的边连通,最小化选中的所有边
的权值和。

Input

第一行三个整数 n, m,d,表示图的点数和边数。接下来的 m行,每行三个整数 ui, vi, wi,表示有一条 ui 与 vi 
之间,权值为 wi 的无向边。
1 <= d <= 4
2d <= n <= 10^4
0 <= m <= 10^4
1 <= ui, vi <= n
1 <= wi <= 1000

Output

一行一个整数,表示答案,如果无解输出-1

题目分析

不同的是,这里只要求$i$和$n-i+1$连通。

用$f[i][j]$表示对于$i$节点,$2d$个点的连通状态为$j$时的最小代价。另用$g[t]$表示全局$t$状态时的最小代价。

若$t$状态可拆成$x,y$两个合法状态,$g[x]+g[y]$也可以用于更新$g[t]$状态。

 #include<bits/stdc++.h>
const int maxn = ;
const int maxm = ;
const int INF = 0x3f3f3f3f; struct Edge
{
int y,val;
Edge(int a=, int b=):y(a),val(b) {}
}edges[maxm];
int n,m,d;
bool vis[maxn];
std::queue<int> q;
int f[maxn][],g[];
int edgeTot,head[maxn],nxt[maxm]; int read()
{
char ch = getchar();
int num = ;
bool fl = ;
for (; !isdigit(ch); ch=getchar())
if (ch=='-') fl = ;
for (; isdigit(ch); ch=getchar())
num = (num<<)+(num<<)+ch-;
if (fl) num = -num;
return num;
}
void spfa(int st)
{
for (int i=; i<=n; i++)
if (f[i][st]!=INF) q.push(i);
while (q.size())
{
int tt = q.front();
q.pop(), vis[tt] = ;
for (int i=head[tt]; i!=-; i=nxt[i])
{
int v = edges[i].y, w = edges[i].val;
if (f[v][st] > f[tt][st]+w){
f[v][st] = f[tt][st]+w;
if (!vis[v]) vis[v] = , q.push(v);
}
}
}
}
bool check(int num)
{
for (int i=; i<d; i++)
if (((num>>i)&)&&((num>>(d+i))&)==) return ;
return ;
}
void addedge(int u, int v)
{
int c = read();
edges[++edgeTot] = Edge(v, c), nxt[edgeTot] = head[u], head[u] = edgeTot;
edges[++edgeTot] = Edge(u, c), nxt[edgeTot] = head[v], head[v] = edgeTot;
}
int main()
{
memset(head, -, sizeof head);
memset(f, 0x3f3f3f3f, sizeof f);
memset(g, 0x3f3f3f3f, sizeof g);
n = read(), m = read(), d = read();
for (int i=; i<=m; i++) addedge(read(), read());
for (int i=; i<=d; i++)
f[i][<<(i-)] = , f[n-i+][<<(d+i-)] = ;
for (int i=; i<<<(d<<); i++)
{
for (int j=; j<=n; j++)
for (int s=i&(i-); s; s=(s-)&i)
f[j][i] = std::min(f[j][i], f[j][s]+f[j][i-s]);
spfa(i);
for (int j=; j<=n; j++) g[i] = std::min(g[i], f[j][i]);
}
for (int i=; i<<<(d<<); i++)
for (int s=i&(i-); s; s=(s-)&i)
if (check(s)&&check(i-s))
g[i] = std::min(g[i], g[s]+g[i-s]);
if (g[(<<(d<<))-] != INF)
printf("%d\n",g[(<<(d<<))-]);
else puts("-1");
return ;
}

END

初涉斯坦纳树&&bzoj4774: 修路的更多相关文章

  1. 【BZOJ4774】修路(动态规划,斯坦纳树)

    [BZOJ4774]修路(动态规划,斯坦纳树) 题面 BZOJ 题解 先讲怎么求解最小斯坦纳树. 先明白什么是斯坦纳树. 斯坦纳树可以认为是最小生成树的一般情况.最小生成树是把所有给定点都要加入到联通 ...

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

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

  3. 【BZOJ4774】修路 [斯坦纳树]

    修路 Time Limit: 20 Sec  Memory Limit: 256 MB Description Input Output 仅一行一个整数表示答案. Sample Input 5 5 2 ...

  4. 「长乐集训 2017 Day8」修路 (斯坦纳树)

    题目描述 村子间的小路年久失修,为了保障村子之间的往来,AAA君决定带领大家修路. 村子可以看做是一个边带权的无向图GGG, GGG 由 nnn 个点与 mmm 条边组成,图中的点从 1∼n1 \si ...

  5. 【BZOJ2595】游览计划(状压DP,斯坦纳树)

    题意:见题面(我发现自己真是越来越懒了) 有N*M的矩阵,每个格子有一个值a[i,j] 现要求将其中的K个点(称为关键点)用格子连接起来,取(i,j)的费用就是a[i,j] 求K点全部连通的最小花费以 ...

  6. HDU 4085 斯坦纳树

    题目大意: 给定无向图,让前k个点都能到达后k个点(保护地)中的一个,而且前k个点每个需要占据后k个中的一个,相互不冲突 找到实现这个条件达到的选择边的最小总权值 这里很容易看出,最后选到的边不保证整 ...

  7. 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 ...

  8. hdu 3311 斯坦纳树

    思路:虚拟一个0号节点,将每个点建一条到0号节点的边,权值为挖井需要的价值.并要保证0号节点同另外n个寺庙一样被选择即可. 然后就是求斯坦纳树了. #include<map> #inclu ...

  9. HDU 3311 Dig The Wells(斯坦纳树)

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=3311 [题意] 给定k座庙,n个其他点,m条边,点权代表挖井费用,边权代表连边费用,问使得k座庙里 ...

随机推荐

  1. JS高级学习历程-3

    JS-作用域链及作用 [作用域链] 1 什么事作用域链 一个变量,在当前环境可以使用,当前环境的内部环境也可以使用,内部的深层环境...也可以使用,变量在不同环境都可以使用的现象想成了一个链条,称为“ ...

  2. Educational Codeforces Round 66 (Rated for Div. 2) B. Catch Overflow!

    链接:https://codeforces.com/contest/1175/problem/B 题意: You are given a function ff written in some bas ...

  3. 汉柏杯&&政治生日6月5日&&端午节

    (一)汉柏杯 前不久汉柏杯2019年计算机设计大赛由我校承办,参加了软件应用开发组竞赛.开发了一个基于微信公众号的求职招聘系统,虽然很low但是貌似还是进了国赛,大概八月十号去安徽芜湖参加国赛决赛.据 ...

  4. Java编码优化

    Java编码优化 1.尽可能使用局部变量 调用方法时传递的参数以及在调用中创建的临时变量都保存在栈中速度较快,其他变 量,如静态变量.实例变量等,都在堆中创建,速度较慢.另外,栈中创建的变量,随 着方 ...

  5. 小G搭积木

    A小 G 搭积木文件名 输入文件 输出文件 时间限制 空间限制box.cpp box.in box.out 2s 128MB题目描述小 G 喜欢搭积木.小 G 一共有 n 块积木,并且积木只能竖着一块 ...

  6. SpringBoot 2.0中SpringWebContext 找不到无法使用的问题解决

    为了应对在SpringBoot中的高并发及优化访问速度,我们一般会把页面上的数据查询出来,然后放到redis中进行缓存.减少数据库的压力. 在SpringBoot中一般使用 thymeleafView ...

  7. 一个很好用的侧滑框架ICSDrawerController实现的 QQ 侧滑及换肤功能

    使用ICSDrawerController 实现侧滑功能 在ICSDrawerController 第三方上做了修改实现,QQ 点击头像打开关抽屉头像渐变的效果 - (void)hiddenHeadV ...

  8. JavaScprit30-6 学习笔记

    今天学习的是  仿即时搜索诗句效果 第一个问题: fetch() Fetch API  提供了一个 JavaScript接口,用于访问和操纵HTTP管道的部分,例如请求和响应.它还提供了一个全局 fe ...

  9. unbuntu&vim&Kali的各种小知识

    1. vmware workstation 15.0.0 2.ubuntu-18.10-desktop  使用网络地址转换 VMware workstation 1.ctrl+alt 返回  unbu ...

  10. HTML5中的webSocket、ajax、http

    本文原链接:https://cloud.tencent.com/developer/article/1115496 https://cloud.tencent.com/developer/articl ...