【题目描述】

参与考古挖掘的小明得到了一份藏宝图,藏宝图上标出了 n 个深埋在地下的宝藏屋,也给出了这 n 个宝藏屋之间可供开发的 m 条道路和它们的长度。

小明决心亲自前往挖掘所有宝藏屋中的宝藏。但是,每个宝藏屋距离地面都很远,也就是说,从地面打通一条到某个宝藏屋的道路是很困难的,而开发宝藏屋之间的道路则相对容易很多。

小明的决心感动了考古挖掘的赞助商, 赞助商决定免费赞助他打通一条从地面到某个宝藏屋的通道,通往哪个宝藏屋则由小明来决定。

在此基础上, 小明还需要考虑如何开凿宝藏屋之间的道路。已经开凿出的道路可以任意通行不消耗代价。每开凿出一条新道路,小明就会与考古队一起挖掘出由该条道路所能到达的宝藏屋的宝藏。另外,小明不想开发无用道路,即两个已经被挖掘过的宝藏屋之间的道路无需再开发。

新开发一条道路的代价是:

这条道路的长度 × 从赞助商帮你打通的宝藏屋到这条道路起点的宝藏屋所经过的宝藏屋的数量(包括赞助商帮你打通的宝藏屋和这条道路起点的宝藏屋)。

请你编写程序为小明选定由赞助商打通的宝藏屋和之后开凿的道路,使得工程总代价最小,并输出这个最小值。

【输入格式】

第一行两个用空格分离的正整数 n 和 m,代表宝藏屋的个数和道路数。

接下来 m 行,每行三个用空格分离的正整数,分别是由一条道路连接的两个宝藏屋的编号(编号为 1~n),和这条道路的长度 v。

【输出格式】

输出共一行,一个正整数,表示最小的总代价。

【样例输入1】

4 5
1 2 1
1 3 3
1 4 1
2 3 4
3 4 1

【样例输出1】

4

【样例1提示】

【样例输入2】

4 5
1 2 1
1 3 3
1 4 1
2 3 4
3 4 2

【样例输出2】

5

【样例2提示】

【数据规模】

对于 20%的数据:

保证输入是一棵树, 1≤n≤8, v≤5000 且所有的 v 都相等。

对于 40%的数据:

1≤n≤8, 0≤m≤1000, v≤5000 且所有的 v 都相等。

对于 70%的数据:

1≤n≤8, 0≤m≤1000, v≤ 5000

对于 100%的数据:

1≤n≤12, 0≤m≤1000, v≤ 500000

就把这道NOIP题当成回坑以后第一篇博吧(丢人

数据范围一眼状压DP,然而好像已经忘了DP怎么玩了

一顿胡乱撕烤,脑洞出一个常数巨大的解法。

F[a]表示联通状态为a的最优方案,G[a][]记录状态a的最优方案对应的每个结点深度,枚举边更新

注意到边数远超过完全图,可以预处理删掉无用边。

然而状态挂在了vector上常数过大,在洛谷上T了一个点,开O2可以A,假装自己过掉了(逃

(UPD6.15 突然发现代码放错了 噫呜呜噫)

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
using namespace std;
typedef long long LL;
int n,m;
const int mxn=;
const int N=<<;
struct edge{
int u,v,w;
int next;
}e[mxn<<];
int hd[mxn],cnt=;
void add_edge(int u,int v,int w){
e[++cnt].u=u;e[cnt].v=v;e[cnt].w=w;
e[cnt].next=hd[u];hd[u]=cnt;
return;
}
int f[N];
struct node{
int dep[];
};
vector<node>g[N];
// node tt,a;
void solve(){
int tmp=<<n;
for(int i=;i<=n;i++){
f[<<(i-)]=;
tt.dep[i-]=;
g[<<(i-)].push_back(tt);
tt.dep[i-]=;
}
for(int i=;i<tmp;i++){
// printf("tmp:%d %d\n",i,f[i]);
for(int u=;u<n;u++){
if( (i&(<<u)) ){
// printf(" u:%d\n",u);
for(int now=;now<g[i].size();now++){
// printf(" now:%d\n",now);
for(int h=hd[u];h;h=e[h].next){ int v=e[h].v;
// printf(" v:%d\n",v);
if(i&(<<v))continue;
// printf(" v:%d\n",v); int tar=i|(<<v);
// printf(" tar:%d\n",tar);
if(f[tar] > f[i] + e[h].w*g[i][now].dep[u] ){
f[tar] = f[i] + e[h].w*g[i][now].dep[u];
a=g[i][now];
a.dep[v]=g[i][now].dep[u]+;
g[tar].clear();
g[tar].push_back(a);
a.dep[v]=;
}
else if(f[tar]== (f[i] + e[h].w*g[i][now].dep[u])){
a=g[i][now];
a.dep[v]=g[i][now].dep[u]+;
g[tar].push_back(a);
a.dep[v]=;
}
}
}
}
}
}
return;
}
int mp[][];
int main(){
int i,j,u,v,w;
scanf("%d%d",&n,&m);
memset(mp,0x3f,sizeof mp);
for(i=;i<=m;i++){
scanf("%d%d%d",&u,&v,&w);
--u;--v;
mp[u][v]=mp[v][u]=min(mp[u][v],w);
}
for(i=;i<n;i++)
for(j=;j<n;j++)
if(mp[i][j]<0x3f3f3f3f)
add_edge(i,j,mp[i][j]);
memset(f,0x3f,sizeof(f));
solve();
printf("%d\n",f[(<<n)-]);
return ;
}

更好的解法是f[a][dep]记录联通状态为a,最深的点深度为dep的最优解,进行转移。

洛谷P3959 [NOIP2017]宝藏的更多相关文章

  1. 洛谷 P3959 NOIP2017 宝藏 —— 状压搜索

    题目:https://www.luogu.org/problemnew/show/P3959 搜索: 不是记忆化,而是剪枝: 邻接矩阵存边即可,因为显然没有那么多边. 代码如下: #include&l ...

  2. 洛谷$P3959\ [NOIp2017]$ 宝藏 状压$dp$

    正解:状压$dp$ 解题报告: 传送门$QwQ$ $8102$年的时候就想搞这题了,,,$9102$了$gql$终于开始做这题了$kk$ 发现有意义的状态只有当前选的点集和深度,所以设$f_{i,j} ...

  3. 【题解】洛谷P3959 [NOIP2017TG] 宝藏(状压DP+DFS)

    洛谷P3959:https://www.luogu.org/problemnew/show/P3959 前言 NOIP2017时还很弱(现在也很弱 看出来是DP 但是并不会状压DP 现在看来思路并不复 ...

  4. 【洛谷P3959】宝藏

    题目大意:比较复杂,点 这里 看题. 题解:对于状态压缩 dp 来讲,阶段的确立十分重要.本题中,采用以层次为阶段进行状压 dp. 设状态 \(f[i][S]\) 表示开凿到深度 \(i\),当前已经 ...

  5. NOIP2017提高组Day2T2 宝藏 洛谷P3959 状压dp

    原文链接https://www.cnblogs.com/zhouzhendong/p/9261079.html 题目传送门 - 洛谷P3959 题目传送门 - Vijos P2032 题意 给定一个 ...

  6. 洛谷P3959 宝藏(NOIP2017)(状压DP,子集DP)

    洛谷题目传送门 Dalao的题解多数是什么模拟退火.DFS剪枝.\(O(3^nn^2)\)的状压DP之类.蒟蒻尝试着把状压改进了一下使复杂度降到\(O(3^nn)\). 考虑到每条边的贡献跟它所在的层 ...

  7. 洛谷P3959——宝藏

    传送门:QAQQAQ 题意: 参与考古挖掘的小明得到了一份藏宝图,藏宝图上标出了$n$个深埋在地下的宝藏屋, 也给出了这$n$个宝藏屋之间可供开发的$m$条道路和它们的长度. 小明决心亲自前往挖掘所有 ...

  8. 【洛谷P3959】[NOIP2017] 宝藏

    宝藏 题目链接 首先,打了一个prim,得了45分 #include<iostream> #include<cstring> #include<cstdio> #i ...

  9. 洛谷 P3959 宝藏 解题报告

    P3959 宝藏 题目描述 参与考古挖掘的小明得到了一份藏宝图,藏宝图上标出了 \(n\) 个深埋在地下的宝藏屋, 也给出了这 \(n\) 个宝藏屋之间可供开发的 \(m\) 条道路和它们的长度. 小 ...

随机推荐

  1. linux的桌面介绍

    一:linux桌面环境 1. X Windows桌面环境 X Windows软件是图形显示的核心部分,是直接和PC上的显卡及显示器打交道的底层程序,它控制着linux程序如何在电脑上显示出漂亮的窗口和 ...

  2. 使用 oracle pipelined 返回一个结果集;

    1.使用 create or replace package refcursor_pkg is -- Author : mr.yang -- Created : 5/14/2017 5:13:42 P ...

  3. Python模块Scrapy导入出错:ImportError: cannot import name xmlrpc_client

    Mac(OS version: OS X Yosemite 10.10.5)上安装Scrapy模块,使用时出现: from six.moves import xmlrpc_client as xmlr ...

  4. HBase 架构与工作原理2 - HBase 组件

    本文系转载,如有侵权,请联系我:likui0913@gmail.com 一.HBase 组件概览 Master-Slave 模式: HBase 体系结构遵循传统的 master-slave 模式,由一 ...

  5. ubuntu16.04 关闭防火墙的方法

    开启防火墙 ufw enable 关闭防火墙 ufw disable

  6. ACM数论之旅17---反演定理 第一回 二项式反演(神说要有光 于是就有了光(´・ω・`))

    终于讲到反演定理了,反演定理这种东西记一下公式就好了,反正我是证明不出来的~(-o ̄▽ ̄)-o 首先,著名的反演公式 我先简单的写一下o( ̄ヘ ̄*o) 比如下面这个公式 f(n) = g(1) + g ...

  7. 基于JVM原理、JMM模型和CPU缓存模型深入理解Java并发编程

    许多以Java多线程开发为主题的技术书籍,都会把对Java虚拟机和Java内存模型的讲解,作为讲授Java并发编程开发的主要内容,有的还深入到计算机系统的内存.CPU.缓存等予以说明.实际上,在实际的 ...

  8. 解决MySQL复制出错 Last_SQL_Errno:1146

    背景:我们在做数据迁移或者拆分的时候,使用Tablespace transcation 这种解决方案时,很有可能就会遇到 从库复制出错,报: Last_SQL_Errno: 1146 那么具体错误内容 ...

  9. LeetCode 717. 1-bit and 2-bit Characters

    We have two special characters. The first character can be represented by one bit 0. The second char ...

  10. 一些常用的基础Linux操作指令

    复习的时候顺便分享我学的知识,虽不是什么牛的技术分享,只是一些基础,基础打好了技术慢慢就提高了!一起加油一起共勉! 具体的vi和vim命令集太多了,以后的随笔我也会分享出来,没必要全记住,记住常用的就 ...