注意到最终图的样子可以看作一条从1到$n$的路径,以及删去这条路径上的边后,路径上的每一个点所对应的一个连通块

考虑dp,令$f_{S,i}$表示当前1到$n$路径上的最后一个点以及之前点(包括$i$)所对应连通块的并,转移考虑枚举下一个点以及其对应的连通块,即$f_{S\cup T,j}=\min(f_{S,i}+sum(S,T)-len(i,j))$

(其中$len(i,j)$表示$(i,j)$这条边的长度,$sum(S,T)=\sum_{x\in S,y\in T,(x,y)\in E}len(x,y)$)

初始状态为$f_{S,1}=0$(其中$1\in S$且$S$的导出子图连通),$f_{other}=\infty$

转移条件为$(i,j)\in E$、$j\in T$、$S\cap T=\empty$且$T$的导出子图连通,因此转移复杂度为$o(n^{2}3^{n})$(关于$T$导出子图连通的这个条件预处理即可)

进一步优化,关于$j$和$T$的枚举可以分开,即先求出$g_{j}=\min(f_{S,i}-len(i,j))$,再枚举包含$j$的$T$即可(这样做的实际意义是先将$S$中所有到$j$的边选择最小的),时间复杂度降为$o(n3^{n})$

  1. 1 #include<bits/stdc++.h>
  2. 2 using namespace std;
  3. 3 #define N 15
  4. 4 struct ji{
  5. 5 int nex,to,len;
  6. 6 }edge[N*N];
  7. 7 int E,n,m,x,y,z,head[N],vis[N],g[N],con[1<<N],sum[1<<N],f[1<<N][N];
  8. 8 void add(int x,int y,int z){
  9. 9 edge[E].nex=head[x];
  10. 10 edge[E].to=y;
  11. 11 edge[E].len=z;
  12. 12 head[x]=E++;
  13. 13 }
  14. 14 void dfs(int k,int s){
  15. 15 if (((s&(1<<k))==0)||(vis[k]))return;
  16. 16 vis[k]=1;
  17. 17 for(int i=head[k];i!=-1;i=edge[i].nex)dfs(edge[i].to,s);
  18. 18 }
  19. 19 int main(){
  20. 20 scanf("%d%d",&n,&m);
  21. 21 memset(head,-1,sizeof(head));
  22. 22 for(int i=1;i<=m;i++){
  23. 23 scanf("%d%d%d",&x,&y,&z);
  24. 24 add(x-1,y-1,z);
  25. 25 add(y-1,x-1,z);
  26. 26 }
  27. 27 memset(f,0x3f,sizeof(f));
  28. 28 for(int i=0;i<(1<<n);i++){
  29. 29 memset(vis,0,sizeof(vis));
  30. 30 for(int j=0;j<n;j++)
  31. 31 if (i&(1<<j)){
  32. 32 dfs(j,i);
  33. 33 break;
  34. 34 }
  35. 35 bool flag=0;
  36. 36 for(int j=0;j<n;j++)
  37. 37 if ((i&(1<<j))&&(!vis[j])){
  38. 38 flag=1;
  39. 39 break;
  40. 40 }
  41. 41 if (!flag){
  42. 42 con[i]=1;
  43. 43 if (i&1)f[i][0]=0;
  44. 44 }
  45. 45 }
  46. 46 for(int i=1;i<(1<<n);i+=2){
  47. 47 if (!con[i])continue;
  48. 48 for(int x=0;x<n;x++){
  49. 49 g[x]=0x3f3f3f3f;
  50. 50 sum[(1<<x)]=0;
  51. 51 }
  52. 52 for(int x=0;x<n;x++)
  53. 53 if ((i&(1<<x))){
  54. 54 for(int j=head[x];j!=-1;j=edge[j].nex){
  55. 55 y=edge[j].to;
  56. 56 if ((i&(1<<y))==0){
  57. 57 g[y]=min(g[y],f[i][x]-edge[j].len);
  58. 58 sum[(1<<y)]+=edge[j].len;
  59. 59 }
  60. 60 }
  61. 61 }
  62. 62 int ii=(1<<n)-1-i;
  63. 63 for(int j=(ii&(ii-1));j>=0;j=((j-1)&ii)){
  64. 64 int jj=(ii^j),k=(jj&(jj-1));
  65. 65 sum[jj]=sum[jj^k]+sum[k];
  66. 66 if (jj==ii)break;
  67. 67 }
  68. 68 for(int x=0;x<n;x++)
  69. 69 for(int j=ii;j;j=((j-1)&ii))
  70. 70 if ((j&(1<<x))&&(con[j]))f[i|j][x]=min(f[i|j][x],g[x]+sum[j]);
  71. 71 }
  72. 72 printf("%d",f[(1<<n)-1][n-1]);
  73. 73 }

[atARC078F]Mole and Abandoned Mine的更多相关文章

  1. Mole and Abandoned Mine

    Mole and Abandoned Mine n点m条边的无向图,删除第i条边花费c[i],问1到n只有一条路径时所需要的最小花费? \(2\le n\le 15\) . 我又A掉了一道zzs的题啦 ...

  2. AT2657 Mole and Abandoned Mine

    传送门 好神的状压dp啊 首先考虑一个性质,删掉之后的图一定是个联通图 并且每个点最多只与保留下来的那条路径上的一个点有边相连 然后设状态:\(f[s][t]\)代表当前联通块的点的状态为\(s\)和 ...

  3. 题解-AtCoder ARC-078F Mole and Abandoned Mine

    problem ATC-arc078F 题意概要:给定一个 \(n\) 点 \(m\) 边简单无向图(无自环无重边),边有费用,现切去若干条边,使得从 \(1\) 到 \(n\) 有且仅有一条简单路径 ...

  4. AtCoder arc078_d Mole and Abandoned Mine

    洛谷题目页面传送门 & AtCoder题目页面传送门 给定一个无向连通带权图\(G=(V,E),|V|=n,|E|=m\)(节点从\(0\)开始编号),要删掉一些边使得节点\(0\)到\(n- ...

  5. AT2657 [ARC078D] Mole and Abandoned Mine

    简要题解如下: 记 \(1\) 到 \(n\) 的路径为关键路径. 注意到关键路径只有一条是解题的关键,可以思考这张图长什么样子. 不难发现关键路径上所有边均为桥,因此大致上是关键路径上每个点下面挂了 ...

  6. 【做题】arc078_f-Mole and Abandoned Mine——状压dp

    题意:给出一个\(n\)个结点的联通无向图,每条边都有边权.令删去一条边的费用为这条边的边权.求最小的费用以删去某些边使得结点\(1\)至结点\(n\)有且只有一条路径. \(n \leq 15\) ...

  7. AtCoder Regular Contest 078

    我好菜啊,ARC注定出不了F系列.要是出了说不定就橙了. C - Splitting Pile 题意:把序列分成左右两部分,使得两边和之差最小. #include<cstdio> #inc ...

  8. 【AtCoder】ARC078

    C - Splitting Pile 枚举从哪里开始分的即可 #include <bits/stdc++.h> #define fi first #define se second #de ...

  9. AtCoder刷题记录

    构造题都是神仙题 /kk ARC066C Addition and Subtraction Hard 首先要发现两个性质: 加号右边不会有括号:显然,有括号也可以被删去,答案不变. \(op_i\)和 ...

随机推荐

  1. Ubuntu20.04安装 maven并配置阿里源

    Ubuntu20.04安装 maven并配置阿里源 sudo apt update sudo apt install maven #安装maven,默认安装路径为/usr/share/maven 添加 ...

  2. Rigidbody钢体移动时抖动问题

    Rigidbody移动时抖动问题 撞墙抖动 Unity中物体移动有非常多的方式: 比如: transform.position += dir*speed*Time.deltaTime; transfo ...

  3. 洛谷4475 巧克力王国(KD-Tree + 维护子树和)

    (嘤嘤嘤 又是一个自闭了一晚上的题) qwq果然不是平面上的点的问题,也可以直接用KDTree打暴力 我们对于巧克力直接建kdtree 维护一个\(mx[i],mn[i]\) 但是有一个非常不友好的事 ...

  4. 一时兴起,用python抓了一下美女图片。实现简单。附上实现代码,可以交流。

    """1.定义目标网址 网址2.数据定位 照片3.数据匹配 标签4.数据下载 下载"""import requestsfrom lxml i ...

  5. PAT (Basic Level) Practice (中文)1007 素数对猜想 (20分)

    1007 素数对猜想 (20分) 让我们定义d​n为:dn = pn+1 − pn,其中p​i是第i个素数.显然有d1 = 1,且对于n > 1有dn是偶数."素数对猜想"认 ...

  6. Java(5)输入和输出

    作者:季沐测试笔记 原文地址:https://www.cnblogs.com/testero/p/15201515.html 博客主页:https://www.cnblogs.com/testero ...

  7. diff算法深入一下?

    文章转自豆皮范儿-diff算法深入一下 一.前言 有同学问:能否详细说一下 diff 算法. 简单说:diff 算法是一种优化手段,将前后两个模块进行差异化比较,修补(更新)差异的过程叫做 patch ...

  8. [no code][scrum meeting] Beta 11

    $( "#cnblogs_post_body" ).catalog() 例会时间:5月26日11:30,主持者:肖思炀 下次例会时间:5月27日11:30,主持者:乔玺华 一.工作 ...

  9. BUAA 2020 软件工程 个人项目作业

    BUAA 2020 软件工程 个人项目作业 Author: 17373051 郭骏 项目 内容 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任健) 这个作业的要求在哪里 个人项目作业 ...

  10. CSS 奇技淫巧 | 巧妙实现文字二次加粗再加边框

    本文将通过一个实际的业务需求,讲解如何实现 极端场景下文字加粗加边框效果 文字多重边框的效果 需求背景 - 文字的二次加粗 今天遇到这样一个有意思的问题: 在文字展示的时候,利用了 font-weig ...