博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【bzoj5180】[Baltic2016]Cities 斯坦纳树
阅读量:5219 次
发布时间:2019-06-14

本文共 2051 字,大约阅读时间需要 6 分钟。

题目描述

给定n个点,m条双向边的图。其中有k个点是重要的。每条边都有一定的长度。
现在要你选定一些边来构成一个图,要使得k个重要的点相互连通,求边的长度和的最小值。

输入

共m+2行
第1行:n,k,m,n个点,k个重要的点,m条边;
第2行共K个点
第3至第m+2行,每行包括3个数字,a,b,c,表示有一条从a到b长度为c的双向路径
k<=5       
n<=10^5   
1<=m<=2*(10^5)

输出

共1行,即最小长度和

样例输入

4 3 6

1 3 4
1 2 4
1 3 9
1 4 6
2 3 2
2 4 5
3 4 8

样例输出

11


题解

斯坦纳树裸题

斯坦纳树:给出一些点,选出若干条边使得这些点连通,求总边权的最值。

斯坦纳树是NPC问题,不存在多项式时间内的解法,求解方法是状压dp。

设 $f[i][j]$ 表示选择若干条边,使得状态为 $i$ 的给定点连通,并且当前可以选择下一条边的端点为 $j$ 的最小边权和。初始状态 $f[2^i][pos[i]]=0$ ,其中 $pos[i]$ 为第 $i$ 个给定点的编号。

那么我们对于每个 $i$ 和 $j$ ,首先枚举 $i$ 的子集 $k$ ,用 $f[k][j]+f[i-k][j]$ 更新 $f[i][j]$ 。

然后再考虑同层转移:如果 $x$ 与 $y$ 边权为 $z$ ,用 $f[i][x]+z$ 更新 $f[i][y]$ ,用 $f[i][y]$ 更新 $f[i][x]$ 。容易发现这个转移就是最短路,因此使用堆优化Dijkstra跑一遍得出所有的 $f[i][j]$ 。

最终答案就是 $min\{f[2^k-1][i]\}$ 

时间复杂度 $O(3^k·n+2^k·m\log n)$ 

#include 
#include
#include
#include
#define N 100010using namespace std;typedef long long ll;typedef pair
pr;priority_queue
q;int head[N] , to[N << 2] , next[N << 2] , cnt , vis[33][N];ll len[N << 2] , f[33][N];inline void add(int x , int y , ll z){ to[++cnt] = y , len[cnt] = z , next[cnt] = head[x] , head[x] = cnt;}int main(){ int n , p , m , i , j , k , x , y; ll z , ans = 1ll << 62; scanf("%d%d%d" , &n , &p , &m); memset(f , 0x3f , sizeof(f)); for(i = 0 ; i < p ; i ++ ) scanf("%d" , &x) , f[1 << i][x] = 0; for(i = 0 ; i < m ; i ++ ) scanf("%d%d%lld" , &x , &y , &z) , add(x , y , z) , add(y , x , z); for(i = 1 ; i < (1 << p) ; i ++ ) { for(j = i ; j ; j = i & (j - 1)) for(k = 1 ; k <= n ; k ++ ) f[i][k] = min(f[i][k] , f[j][k] + f[i ^ j][k]); for(j = 1 ; j <= n ; j ++ ) q.push(pr(-f[i][j] , j)); while(!q.empty()) { x = q.top().second , q.pop(); if(vis[i][x]) continue; vis[i][x] = 1; for(j = head[x] ; j ; j = next[j]) if(f[i][to[j]] > f[i][x] + len[j]) f[i][to[j]] = f[i][x] + len[j] , q.push(pr(-f[i][to[j]] , to[j])); } } for(i = 1 ; i <= n ; i ++ ) ans = min(ans , f[(1 << p) - 1][i]); printf("%lld\n" , ans); return 0;}

 

转载于:https://www.cnblogs.com/GXZlegend/p/8485780.html

你可能感兴趣的文章
runC爆严重安全漏洞,主机可被攻击!使用容器的快打补丁
查看>>
Maximum Product Subarray
查看>>
solr相关配置翻译
查看>>
通过beego快速创建一个Restful风格API项目及API文档自动化(转)
查看>>
解决DataSnap支持的Tcp长连接数受限的两种方法
查看>>
Synchronous/Asynchronous:任务的同步异步,以及asynchronous callback异步回调
查看>>
ASP.NET MVC5 高级编程-学习日记-第二章 控制器
查看>>
Hibernate中inverse="true"的理解
查看>>
高级滤波
查看>>
使用arcpy添加grb2数据到镶嵌数据集中
查看>>
[转载] MySQL的四种事务隔离级别
查看>>
QT文件读写
查看>>
C语言小项目-火车票订票系统
查看>>
15.210控制台故障分析(解决问题的思路)
查看>>
BS调用本地应用程序的步骤
查看>>
常用到的多种锁(随时可能修改)
查看>>
用UL标签+CSS实现的柱状图
查看>>
mfc Edit控件属性
查看>>
Linq使用Join/在Razor中两次反射取属性值
查看>>
[Linux]PHP-FPM与NGINX的两种通讯方式
查看>>