【题目描述】

参与考古挖掘的小明得到了一份藏宝图,藏宝图上标出了 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. php推送

    需求: 我想做个会员站内通知的功能.不想用以前的ajax查询,听说有个推技术.以下文章介绍的不错,来自转载, ============================================= ...

  2. LDA-Latent Dirichlet Allocation 学习笔记

    以下内容主要基于<Latent Dirichlet Allocation>,JMLR-2003一文,另加入了一些自己的理解,刚开始了解,有不对的还请各位指正. LDA-Latent Dir ...

  3. TFS(Team Foundation Server) 权限设置记录

    环境: TFS2012 + win7 1.安装好TFS 2.创建系统用户组: TFSAdmins.TFSDevs.TFSUsers 分别为TFS管理人员组.TFS开发人员组.TFS普通用户组. 如下图 ...

  4. Smallest Minimum Cut HDU - 6214(最小割集)

    Smallest Minimum Cut Time Limit: 2000/2000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Oth ...

  5. [洛谷P4723]【模板】线性递推

    题目大意:求一个满足$k$阶齐次线性递推数列$a_i$的第$n$项. 即:$a_n=\sum\limits_{i=1}^{k}f_i \times a_{n-i}$ 题解:线性齐次递推,先见洛谷题解, ...

  6. BZOJ 3357: [Usaco2004]等差数列

    3357: [Usaco2004]等差数列 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 338  Solved: 160[Submit][Statu ...

  7. BZOJ4037:[HAOI2015]数字串拆分——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=4037 你有一个长度为n的数字串.定义f(S)为将S拆分成若干个1~m的数的和的方案数,比如m=2时 ...

  8. 【Learning】分数规划

    分数规划 ​ 分数规划是一类决策性问题.一般地,题目会要求你针对问题规划一种方案,使得其代价函数最小或最大.其中,代价函数一般是分数形式,且分子分母的构成元素一般呈现一一对应关系. 直接上例题观察:B ...

  9. 用Python实现的数据结构与算法:链表

    一.概述 链表(linked list)是一组数据项的集合,其中每个数据项都是一个节点的一部分,每个节点还包含指向下一个节点的链接(参考 <算法:C语言实现>). 根据结构的不同,链表可以 ...

  10. wget递归下载整站

    由于线上跑的系统还有CentOS5.4.6.4.6.5.6.5.6.6.6.8,而各镜像站维护的最早的版本已经是6.9,所以需要爬archive站点的rpm包来自建yum仓库. # wget -r - ...