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

\(n \leq 15\)

不难想象出,删去边后所得的图形中,在\(1\)到\(n\)的路径上的每一条边都是桥。换言之,每一条边都连接两个边双联通分量。 \(n \leq 15\)的数据范围显然与状压dp有关,于是我们考虑枚举下一个边双联通分量来完成dp转移,以不断铺设从\(1\)到\(n\)的路径。

令dp状态为dp[S,cur],其中\(S\)为当前已被选的点的集合,且\(1\)到\(n\)的路径以铺设到\(cur\)。那么,我们的转移就是铺设下一个结点,或新增一个包含\(cur\)的边双(不包含\(S\)中的其他结点)。这样,如果记两个集合\(S\),\(T\) 之间所有边的和为co[S,T],我们就能得到转移方程:

  • \[{\rm{dp}}[S \bigcup \{ u \},u] = {\rm dp}[S,cur] +{\rm co}[\{ u \},S - \{ cur \}]
    \]

  • \[{\rm dp}[S \bigcup T,cur] = {\rm dp} [S,cur] + {\rm co}[T,S - \{ cur \}]
    \]

复杂度是\(O(n \times 3^n)\)。

上面的转移是从题解上抄来的(划。它与直接枚举下一个边双和路径上的结点的做法相比,复杂度上更优越。(后者的复杂度是\(O(n^2 \times 3^n)\)。

顺便一提,co所占用的空间是\(O(3^n)\)的,并且在dp时要注意第一条方程中\(u\)和\(cur\)必须相邻。

#include <bits/stdc++.h>
#define lowbit(x) ((x) & (- (x)))
#define rev(x) (((1 << n) - 1) ^ x)
#define R register
using namespace std;
const int N = 15, MAX = 1 << 15, MAX3 = 14348907, INF = 0x3f3f3f3f;
int n,m,su[N+2][MAX],dp[MAX][N + 2],trans[MAX],co[MAX3];
int main() {
int x,y,z;
scanf("%d%d",&n,&m);
for (int i = 1 ; i <= m ; ++ i) {
scanf("%d%d%d",&x,&y,&z);
su[x][1 << y >> 1] += z;
su[y][1 << x >> 1] += z;
}
for (int i = 1 ; i <= n ; ++ i)
for (R int j = 1 ; j < (1 << n) ; ++ j)
su[i][j] = su[i][j - lowbit(j)] + su[i][lowbit(j)];
for (R int i = 1 ; i < (1 << n) ; ++ i) {
for (int j = 1, t = 1 ; j <= n ; ++ j, t *= 3)
if ((i >> j-1)&1) trans[i] += t;
}
for (R int i = 1 ; i < (1 << n) ; ++ i)
for (R int j = rev(i) ; j ; j = (j-1)&rev(i)) {
int t = trans[i] + 2 * trans[j];
for (int k = 1 ; k <= n ; ++ k)
if ((i >> k-1)&1) co[t] += su[k][j];
}
memset(dp,0x3f,sizeof dp);
dp[1][1] = 0;
for (R int i = 1 ; i < (1 << n) ; ++ i) {
for (int j = 1 ; j <= n ; ++ j) if ((i >> j-1)&1) {
if (dp[i][j] == INF) continue;
for (R int k = rev(i) ; k ; k = (k-1)&rev(i)) if (su[j][k] > 0)
dp[i | k][j] = min(dp[i|k][j],dp[i][j]+co[trans[i^(1<<j>>1)]+2*trans[k]]);
if ((i >> n-1)&1) continue;
for (int k = 1 ; k <= n ; ++ k) if (!((i >> k-1)&1)) if (su[k][1<<j>>1] > 0)
dp[i|(1<<k>>1)][k] = min(dp[i|(1<<k>>1)][k],dp[i][j]+su[k][i^(1<<j>>1)]);
}
}
printf("%d\n",dp[(1 << n) - 1][n]);
return 0;
}

小结:在dp转移时把一步拆成两步,是可以减小复杂度的。

【做题】arc078_f-Mole and Abandoned Mine——状压dp的更多相关文章

  1. 刷题向》关于第一篇状压DP BZOJ1087 (EASY+)

    这是本蒟蒻做的第一篇状压DP,有纪念意义. 这道题题目对状压DP十分友善,算是一道模板题. 分析题目,我们发现可以用0和1代表每一个格子的国王情况, 题目所说国王不能相邻放置,那么首先对于每一行是否合 ...

  2. [思路题][LOJ2290][THUWC2017]随机二分图:状压DP+期望DP

    分析 考虑状压DP,令\(f[sta]\)表示已匹配状态是\(sta\)(\(0\)代表已匹配)时完美匹配的期望数量,显然\(f[0]=1\). 一条边出现了不代表它一定在完美匹配内,这也导致很难去直 ...

  3. [WC2008]游览计划 状压DP,斯坦纳树

    ---题面--- 题解: 这是一道斯坦纳树的题,用状压+spfa来解决 什么是斯坦纳树? 一开始还以为是数据结构来着,其实跟最小生成树很像,大致就是最小生成树只能在各个点之间直接相连,而斯坦纳树则允许 ...

  4. POJ 1185 炮兵阵地 (状压DP)

    题目链接 题意 : 中文题不详述. 思路 :状压DP,1表示该位置放炮弹,0表示不放.dp[i][j][k],代表第 i 行的状态为k时第i-1行的状态为 j 时放置的最大炮弹数.只是注意判断的时候不 ...

  5. poj 3254Corn Fields (入门状压dp)

    Farmer John has purchased a lush ≤ M ≤ ; ≤ N ≤ ) square parcels. He wants to grow some yummy corn fo ...

  6. HDU4623 CRIME 【状压DP】【同类项合并】

    题目大意: 求相邻元素互质的排列个数. 题目分析: 由于互质只与质因数有关,所以我们对于质因数种类相同的数合并为一类,特殊的,1,17,19,23是一类,因为没有数与他们不互质. 那么我们做各个位进制 ...

  7. HaHa's Morning(状压DP)

    描述 HaHa is so happy today, he is going to participate the 7th Hunan University Programming Contest. ...

  8. 【状压dp】Hamiton路径

    描述 给定一张 n(n≤20) 个点的带权无向图,点从 0~n-1 标号,求起点 0 到终点 n-1 的最短Hamilton路径. Hamilton路径的定义是从 0 到 n-1 不重不漏地经过每个点 ...

  9. Mole and Abandoned Mine

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

随机推荐

  1. sqlserver恢复数据库被挂起

    已测试过,直接执行此句后,数据库恢复原状态.数据不会丢失.具体是什么意思,暂时没来得及搞明白 RESTORE database dbname with norecovery

  2. sql server 将两列的值合并到另一列

    select top 100 t2.FullName, * from Subject,(select id, isnull(first_name,'') +isnull(middle_name,'') ...

  3. uvalive 5731 Qin Shi Huang’s National Road System

    题意: 秦始皇要修路使得所有的城市连起来,并且花费最少:有一个人,叫徐福,他可以修一条魔法路,不花费任何的钱与劳动力. 秦始皇想让修路的费用最少,但是徐福想要受益的人最多,所以他们经过协商,决定让 A ...

  4. ext2文件系统的运行—superblock/inode/block

    鸟哥私房菜书上内容: superblock:记录此 filesystem 的整体信息,包括inode/block的总量.使用量.剩余量, 以及文件系统的格式与相关信息等:inode:记录文件的属性,一 ...

  5. 20165305 实验四:Android程序设计

    实验内容 基于Android Studio开发简单的Android应用并部署测试; 了解Android.组件.布局管理器的使用: 掌握Android中事件处理机制. Android Studio安装 ...

  6. pip使用简要说明

    一.pip常用命令 安装指定包 pip install SomePackage #最新版本 安装指定包 pip install SomePackage==1.0.4 #指定版本 安装指定包 pip i ...

  7. C# 自定义承载控件

    例如ToolStripTextBox类,里面的封装就是一个TextBox控件..NET的类库提供了ToolStripComBox和ToolStripProgressBar两个类.这些类都是从ToolS ...

  8. idea 项目转 eclipse项目

    接到一个很紧急的活,我很着急,也很兴奋,打开邮件一看,有点懵逼.   idea项目.idea不熟啊,网上搜攻略.我做个总结,归根结底就是一句话.   下个idea,然后一步一步的安装好.   然后也是 ...

  9. 使用 ffmpeg 转换视频格式

    ffmpeg 是 *nix 系统下最流行的音视频处理库,功能强大,并且提供了丰富的终端命令,实是日常视频处理的一大利器! 实例 flac 格式转 mp3 音频格式转换非常简单: ffmpeg -i i ...

  10. 常用linux命令行

    1.ls命令 ls -a 列出目录所有文件,包含以.开始的隐藏文件 ls -A 列出除.及..的其它文件 ls -r 反序排列 ls -t 以文件修改时间排序 ls -S 以文件大小排序 ls -h ...