题意:

对于边带权的无向图 G = (V, E),请选择一些边,

使得1<=i<=d,i号节点和 n − i + 1 号节点可以通过选中的边连通,

最小化选中的所有边的权值和。

d<=4 n<=10000 m<=10000 w[i]<=1000

思路:

求一个最小生成树(或森林),使得若干组点对各自联通
由于d很小(<=4),考虑采用状压DP的做法。
令1,2,..d和n,n-1...n-d+1为2d个特殊点
先考虑生成树的情况:设F[i][j](i=1,2...n j为一个2d位的2进制)表示以第i个点为根,当前生成树包含特殊点的情况为j的最小代价
一共有两种转移方法:
① F[i][j]+F[i][k]-->F[i][j|k]
② F[i][j]+edg[i][k]-->F[k][j]
初始条件(d=3为例)F[1][000001]=F[2][000010]=F[3][000100]=F[n-2][001000]=F[n-1][010000]=F[n][100000]=0,其余F=inf
从小到大枚举j(0...1<<(2*d)-1)
对每个j,再枚举i和(j的一个子集k),F[i][j]=min{F[i][k]+F[i][j-k]}
对第二种转移按照多源最短路的方式跑spfa
得到F后再考虑怎么求生成森林答案
令G[i]表示当前点对联通状态为i时的最小代价(如i=011时表示第一个点对(1,n)不连通,第二和三个点对(2,n-1),(3,n-2)连通)
则G[i]=min{G[j]+G[i-j],F[k][p]}(j是i的子集,k=1,2,....n,p表示i代表的点对的所有点的状压形式,如i=001,代表(3,n-2),此时p=001100)}
最后答案就是G[(1<<d)-1]

时间复杂度:求F O(3^(2*d)*n /*第一步*/ + 2^(2*d)*spfa(n,m) /*第二步*/ ),求G复杂度远低于F,可忽略
空间复杂度:F数组O(n*2^(2*d)),G忽略

 const oo=;
var head,vet,next,len:array[..]of longint;
dp:array[..,..]of longint;
g:array[..]of longint;
q:array[..]of longint;
inq:array[..]of boolean;
n,m,sta,i,j,tot,d,x,y,z,s,v,sum:longint; function min(x,y:longint):longint;
begin
if x<y then exit(x);
exit(y);
end; procedure add(a,b,c:longint);
begin
inc(tot);
next[tot]:=head[a];
vet[tot]:=b;
len[tot]:=c;
head[a]:=tot;
end; procedure spfa(sta:longint);
var i,t,w,u,e,v:longint;
begin
t:=; w:=;
for i:= to n do
begin
inc(w); q[w]:=i; inq[i]:=true;
end;
while t<w do
begin
inc(t); u:=q[t mod ]; inq[u]:=false;
e:=head[u];
while e<> do
begin
v:=vet[e];
if dp[u,sta]+len[e]<dp[v,sta] then
begin
dp[v,sta]:=dp[u,sta]+len[e];
if not inq[v] then
begin
inc(w); q[w mod ]:=v; inq[v]:=true;
end;
end;
e:=next[e];
end;
end;
end; begin
assign(input,'road.in'); reset(input);
assign(output,'road.out'); rewrite(output);
readln(n,m,d);
for i:= to m do
begin
readln(x,y,z);
add(x,y,z);
add(y,x,z);
end;
sum:=<<(d<<);
for i:= to sum- do
for j:= to n do dp[j,i]:=oo;
for i:= to d do
begin
dp[i,<<(i-)]:=;
dp[n-i+,<<(i+d-)]:=;
end; for sta:= to sum- do
begin
for i:= to n do
begin
v:=sta-;
while v> do
begin
dp[i,sta]:=min(dp[i,sta],dp[i,v]+dp[i,sta xor v]);
v:=sta and (v-);
end;
end;
spfa(sta);
end;
sum:=<<d;
for sta:= to sum- do
begin
g[sta]:=oo;
for i:= to n do g[sta]:=min(g[sta],dp[i,sta or (sta<<d)]);
end;
for sta:= to sum- do
begin
v:=sta-;
while v> do
begin
g[sta]:=min(g[sta],g[v]+g[sta xor v]);
v:=sta and (v-);
end;
end;
if g[sum-]<oo then writeln(g[sum-])
else writeln(-); close(input);
close(output);
end.

【ZJOI2017 Round1练习&BZOJ4774】D3T2 road(斯坦纳树,状压DP)的更多相关文章

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

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

  2. bzoj 4006 [JLOI2015]管道连接(斯坦纳树+状压DP)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=4006 [题意] 给定n点m边的图,连接边(u,v)需要花费w,问满足使k个点中同颜色的 ...

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

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

  4. BZOJ2595: [Wc2008]游览计划(斯坦纳树,状压DP)

    Time Limit: 10 Sec  Memory Limit: 256 MBSec  Special JudgeSubmit: 2030  Solved: 986[Submit][Status][ ...

  5. 绿色计算大赛决赛 第二阶段 消息传递(斯坦纳树 状压dp+spfa)

    传送门 Description 作为公司老板的你手下有N个员工,其中有M个特殊员工.现在,你有一个消息需要传递给你的特殊员工.因为你的公司业务非常紧张,所以你和员工之间以及员工之间传递消息会造成损失. ...

  6. bzoj1402 Ticket to Ride 斯坦纳树 + 状压dp

    给定\(n\)个点,\(m\)条边的带权无向图 选出一些边,使得\(4\)对点之间可达,询问权值最小为多少 \(n \leqslant 30, m \leqslant 1000\) 首先看数据范围,\ ...

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

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

  8. 【ZJOI2017 Round1练习】D4T2 trie(贪心,状压DP)

    题意:现在 Matej 手上有 N 个英文小写字母组成的单词, 他想知道,如果将这 N 个单词中的字母分别进行重新排列,形成的字母树的节点数最少是多少. n<=16,len[i]<=100 ...

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

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

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

随机推荐

  1. 转 Dockerfile 常用指令 - 每天5分钟玩转 Docker 容器技术(16)

    是时候系统学习 Dockerfile 了. 下面列出了 Dockerfile 中最常用的指令,完整列表和说明可参看官方文档. FROM指定 base 镜像. MAINTAINER设置镜像的作者,可以是 ...

  2. 424 Longest Repeating Character Replacement 替换后的最长重复字符

    给你一个仅由大写英文字母组成的字符串,你可以将任意位置上的字符替换成另外的字符,总共可最多替换 k 次.在执行上述操作后,找到包含重复字母的最长子串的长度.注意:字符串长度 和 k 不会超过 104. ...

  3. APP多渠道打包

    多渠道打包的概念: 打包是指使用证书文件对app签名生成一个apk文件. 多渠道打包指的就是我们的app在开发完成之后需要投放到不同的市场,比如说Google市场.百度市场等,为了统计应用在各个市场的 ...

  4. SP CAML工具

    直接一直使用CAML做一些简单的SP列表查询,突然想对CAML进一步了解,于是找到两个常用工具,做以记录: 1 Caml Query Builder : 用于编写CAML查询,对初学者可以了解查询语句 ...

  5. Oracle分区表例子

    分区表 Oracle提供的分区方法有以下几种. 1.范围分区(range) 范围分区是应用范围比较广的表分区方式,它是以列的值的范围来作为分区的划分条 件,将记录存放到列值所在的 range分区中. ...

  6. RFTWEB测试对象抓取的方法

    本文转自:http://feiyeguohai.iteye.com/blog/1468576 Rational Functional Tester (RFT) 作为 IBM 自己设计研发的自动化测试工 ...

  7. OpenGl之旅-—如何使用code blocks创建一个opengl项目

    开始学习opengl啦,练习用的编辑器是code blocks. 首先当然是要清楚如何使用code blocks创建一个opengl项目了. 首先必须先引用opengl的库glut,网上百度下载一个完 ...

  8. 掌握Spark机器学习库-07.6-线性回归实现房价预测

    数据集 house.csv 数据概览 代码 package org.apache.spark.examples.examplesforml import org.apache.spark.ml.fea ...

  9. java调用jacob生成pdf,word,excel横向

    /* * 传进一个office文件的byte[]以及后缀,生成一个pdf文件的byte[] */ public byte[] jacob_Office2Pdf(byte[] srcFileBytes, ...

  10. 博客之旅 gogogo!

    听说写博客的人都很牛~ 上班一年多了,想记录点什么,so,就写博客吧,整理一些技术点与工作生活心得 欢迎各位道友交流学习 :)