初涉斯坦纳树&&bzoj4774: 修路
斯坦纳树的基础应用
斯坦纳树有什么用
个人一点粗浅理解……
最基本形式的斯坦纳树问题(以下简称母问题):给定图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 斯坦纳树
【dp套斯坦纳树】bzoj4774: 修路
Description
Input
Output
题目分析
不同的是,这里只要求$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: 修路的更多相关文章
- 【BZOJ4774】修路(动态规划,斯坦纳树)
[BZOJ4774]修路(动态规划,斯坦纳树) 题面 BZOJ 题解 先讲怎么求解最小斯坦纳树. 先明白什么是斯坦纳树. 斯坦纳树可以认为是最小生成树的一般情况.最小生成树是把所有给定点都要加入到联通 ...
- 【BZOJ4774/4006】修路/[JLOI2015]管道连接 斯坦纳树
[BZOJ4774]修路 Description 村子间的小路年久失修,为了保障村子之间的往来,法珞决定带领大家修路.对于边带权的无向图 G = (V, E),请选择一些边,使得1 <= i & ...
- 【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座庙里 ...
随机推荐
- Glassfish 4 修改server.log 等配置
如果所示:
- GZS与小公园(DFS)
Description 某天GZS漫步在学校新建的小公园,他发现那里建成了一些水池和小河道.我们暂且把它们统一看成水池.假设公园旁有一张小公园的地图,上面仅标识了此处是否是水池,你能帮GZS计算出该地 ...
- Hive_Hive的数据模型_视图
- 视图是一种虚表,是一个逻辑概念:可以跨越多张表- 视图建立在已有表的基础上,视图赖以建立的这些表称为基表.- 视图可以简化复杂的查询. 创建视图 create view viewName as s ...
- jQuery实现全选反选功能
废话不说,直接上代码! <html> <head> <meta http-equiv="Content-Type" content="tex ...
- TDH-ssh免密登录
[root@tw-node118 ~]# ssh-keygen -t rsa -P '' 这个指令会在/root/.ssh下生成id_rsa和id_rsa.pub文件.看一下/root/.ssh下的文 ...
- PHP的时间函数strtotime
时间加减 [php] view plaincopy <?php //获取本地 提取年份+1 $date=date("Y-m-d",mktime(0,0,0,date(&quo ...
- Vue2之页面 、js 、css分离
在编写vue的时候,页面数据少的时候,可以将所有的js和css都可以直接写在页面上,但是页面数据多,js.css的方法和样式多的时候,都放在一个页面的时候,就显得页面vue十分的臃肿. 所以写项目的时 ...
- (译)Cg Programming/Unity(Cg编程/Unity)
最近在学习Unity3d中的shader编程,能找到的中文资料比较少,于是,尝试翻译一下wiki Books上的资料,以方便其他跟我一样的入门学习者.由于是第一次翻译技术资料,经验不足,难免出错,请路 ...
- 用于<挣值管理>的各种指标计算
PV(Planning Value) 含义:计划价值,截至到某个时间计划工作经批准的成本预算. 公式:PV=计划工作数X计划单价. BAC 含义:完工预算,截至到完工时间计划工作经批准的成本预算,即完 ...
- JAVA 框架之面向对象设计原则
面向对象设计原则: 单一职责原则 SRP : 一个类或者行为只做一件事 . 降低代码冗余,提高可重用性,可维护性,可扩展性,可读性 使用组合形式 里氏替换原则 LSP : 所有引用基类 ...