斯坦纳树的基础应用

斯坦纳树有什么用

个人一点粗浅理解……

最基本形式的斯坦纳树问题(以下简称母问题):给定图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. maven scope 以及依赖传递

    https://www.cnblogs.com/mxm2005/p/4947905.html

  2. shell脚本编程入门

    Linux的Shell种类众多,这里我们关注的重点是Bash. 基本语法 环境变量$PATH IO重定向:  以<改变标准输入 如:tr -d '\r' < dos-file.txt 以& ...

  3. CF 1215解题报告

    T1 偶数输出n/2 奇数输出(n-1)/2即可 T2 判断是不是回文 不是直接输出子串 是回文继续判断 如果他前(len+1)/2内没有相同 输出-1 其他的 交换不同字符,输出子串 T3 贪心+二 ...

  4. Codeforces 1168A(二分check)

    关键是check.要注意到其实有了mid以后每个位置都是独立的,它能从哪走到哪是固定了的,只要从左到右尽量贪心压着最小值即可. #include <cstdio> const int ma ...

  5. tomcat7 fail to start inside Ubuntu Docker container

    The tomcat startup script needs some special privileges. Concrete it needs to check all running proc ...

  6. HDU 1027 G - Can you answer these queries?

    http://acm.hdu.edu.cn/showproblem.php?pid=4027 Can you answer these queries? Time Limit: 4000/2000 M ...

  7. spark-2.2.0-bin-hadoop2.6和spark-1.6.1-bin-hadoop2.6发行包自带案例全面详解(java、python、r和scala)之Basic包下的JavaPageRank.java(图文详解)

    不多说,直接上干货! spark-1.6.1-bin-hadoop2.6里Basic包下的JavaPageRank.java /* * Licensed to the Apache Software ...

  8. 超全面的vue.js使用总结

    一.Vue.js组件 vue.js构建组件使用 Vue.component('componentName',{ /*component*/ }): 这里注意一点,组件要先注册再使用,也就是说: Vue ...

  9. Webstorm 激活

    注册时,在打开的License Activation窗口中选择“License server”,在输入框输入下面的网址: http://idea.iteblog.com/key.php 点击:Acti ...

  10. c#ADSL拨号类

    class ADSLHelper { /// <summary> ///拨号 /// </summary> /// <param name="connectio ...