AtCoder arc078_d Mole and Abandoned Mine
洛谷题目页面传送门 & AtCoder题目页面传送门
给定一个无向连通带权图\(G=(V,E),|V|=n,|E|=m\)(节点从\(0\)开始编号),要删掉一些边使得节点\(0\)到\(n-1\)有且只有\(1\)条简单路径,求最小的删掉的边的权值和。
\(n\in[2,15],m\in\left[n-1,\dfrac{n(n-1)}2\right]\),\(G\)中没有重边或自环。
这个问题显然可以转化为:求最大的删过边之后的图的边权和,再用原图的边权和减去它。
考率删过边之后的图\(G'(V,E')\)的样子。\(0\to n-1\)只有\(1\)条简单路径,设它为\(pa\left(pa_1=0,pa_s=n-1,\forall i\in[1,s),(pa_i,pa_{i+1},len)\in E'\right)\)。若\(\exists i\in[1,s],\exists j\in[i+1,s]\),\(pa_i\to pa_j\)有不止\(1\)条简单路径,那么显然可以先走\(0\to pa_i\),然后分别走\(pa_i\to pa_j\)的多条路径,最后走\(pa_j\to n-1\),构造出多条\(0\to n-1\)路径,不符合题意。可以得到\(\forall i\in[1,s],\forall j\in[i+1,s]\),\(pa_i\to pa_j\)只有\(1\)条简单路径。所以\(G'\)应该是这样的:\(pa\)中每个点下面挂着几坨连通的点,各个点挂的点集没有交集(如果有交集,那么这\(2\)个\(pa\)中的点之间的简单路径就会不止\(1\)条)。
最优情况下,\(G'\)一定是连通的。理由:若\(G'\)不连通,由于\(G'\)合法,\(0,n-1\)一定在一个连通分量内。那么可以在除了\(0,n-1\)所在连通分量的其他连通分量之间恢复若干被删除的边使得它们连通(由于原图\(G\)连通,一定可行)。此时\(G'\)还剩\(2\)个连通分量,设它们分别为\(A,B\),其中\(0,n-1\in A\)。由于原图\(G\)连通,一定可以找到一组点\((a,b)\)使得\(a\in A,b\in B,(a,b,len)\in E\),将\((a,b,len)\)恢复,这样\(B\)就成为了挂在\(pa\)中点下新的一坨点或某坨旧点的一份子。如此,可以在\(G'\)上恢复若干被删除的边,使得它更优且合法。所以最优情况下,\(G'\)一定是连通的。
接下来,利用任意\(2\)坨点都没有交集这个性质,就可以状压DP了。设\(dp_{i,j}(0\in i)\)表示\(pa\)中\(0\to j\)这条链包括它们下面挂的那些坨点所构成的点集为bitmask\(i\)时,\(\left\{(x,y,len)\mid x,y\in i,(x,y,len)\in E\right\}\)中可以留下的边的最大权值和。显然,目标为\(\sum\limits_{(x,y,len)\in E}len-dp_{V,n-1}\),边界为\(dp_{i,0}=\sum\limits_{x,y\in i,(x,y,len)\in E}len\)。转移时,枚举\(j\)下挂的点集,这个点集和\(\{j\}\)的并集中显然应该所有的边都留下,再枚举\(pa\)中\(j\)的前一个点,这个点到\(j\)的边也应该留下。于是状态转移方程就出来了:
\]
这里面有个子集枚举,所以直接按照这个方程转移是\(\mathrm O\!\left(3^nn^3\right)\)的,过不去。显然,可以预处理出\(sum_i=\sum\limits_{x,y\in i,(x,y,len)\in E}len\),复杂度降到了\(\mathrm O\!\left(3^nn^2\right)\),但还是过不去。接下来要处理\(\max\limits_{o\in i-k-\{j\},(o,j,len)\in E}\left\{len+dp_{i-k-\{j\},o}\right\}\),不难发现这个式子仅关于\(i-k-\{j\}\)和\(j\),而不同的二元组\((i-k-\{j\},j)\)只有\(\mathrm O(2^nn)\)个,这个式子却被计算了\(\mathrm O(3^nn)\)次。于是我们可以避免重复计算,记录\(tmp_{i,j}=\max\limits_{k\in i,(k,j,len)\in E}\left\{len+dp_{i,k}\right\}\),在每次完成一个\(dp_{i,j}\)的计算时,更新所有与它相关的\(tmp\)的值,即令\(\forall k\notin i((j,k,len)\in E),tmp_{i,k}=\max(tmp_{i,k},len+dp_{i,j})\)。这样,在状态转移方程中遇到这个式子时,直接调用\(tmp\)即可。
放一下最终的状态转移方程:
\]
时间复杂度\(\mathrm O\!\left(3^nn+2^nn^2\right)=\mathrm O(3^nn)\)。
最后上代码:
#include<bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
const int N=15;
int n,m;
int tb[N][N];//邻接矩阵
int sum[1<<N];
int tmp[1<<N][N],dp[1<<N][N];
void prt_bitmsk(int x){
for(int i=0;i<n;i++)cout<<!!(x&1<<i);
}
int main(){
cin>>n>>m;
int tot=0;
while(m--){
int x,y,z;
cin>>x>>y>>z;
x--;y--;
tb[x][y]=tb[y][x]=z;
tot+=z;
}
for(int i=0;i<1<<n;i++){//预处理sum
for(int j=0;j<n;j++)if(i&1<<j)for(int k=j+1;k<n;k++)if(i&1<<k)
sum[i]+=tb[j][k];
// printf("sum[");prt_bitmsk(i);printf("]=%d\n",sum[i]);
}
for(int i=0;i<1<<n;i++)for(int j=0;j<n;j++)dp[i][j]=tmp[i][j]=-inf;//初始化
for(int i=0;i<1<<n;i++)if(i&1)for(int j=0;j<n;j++)if(i&1<<j){//DP
if(j)//非边界
for(int k=i^1<<j^1;;k=k-1&(i^1<<j^1)){//枚举j下面挂的点集k
dp[i][j]=max(dp[i][j],sum[k|1<<j]+tmp[i^k^1<<j][j]);//状态转移方程
if(!k)break;
}
else//边界
dp[i][j]=sum[i];
// printf("dp[");prt_bitmsk(i);printf("][%d]=%d\n",j,dp[i][j]);
for(int k=0;k<n;k++)if(!(i&1<<k))//更新与dp[i][j]有关的所有tmp[i][k]
if(tb[j][k])
tmp[i][k]=max(tmp[i][k],dp[i][j]+tb[j][k]);
}
cout<<tot-dp[(1<<n)-1][n-1];//目标
return 0;
}
AtCoder arc078_d Mole and Abandoned Mine的更多相关文章
- 题解-AtCoder ARC-078F Mole and Abandoned Mine
problem ATC-arc078F 题意概要:给定一个 \(n\) 点 \(m\) 边简单无向图(无自环无重边),边有费用,现切去若干条边,使得从 \(1\) 到 \(n\) 有且仅有一条简单路径 ...
- Mole and Abandoned Mine
Mole and Abandoned Mine n点m条边的无向图,删除第i条边花费c[i],问1到n只有一条路径时所需要的最小花费? \(2\le n\le 15\) . 我又A掉了一道zzs的题啦 ...
- AT2657 Mole and Abandoned Mine
传送门 好神的状压dp啊 首先考虑一个性质,删掉之后的图一定是个联通图 并且每个点最多只与保留下来的那条路径上的一个点有边相连 然后设状态:\(f[s][t]\)代表当前联通块的点的状态为\(s\)和 ...
- [atARC078F]Mole and Abandoned Mine
注意到最终图的样子可以看作一条从1到$n$的路径,以及删去这条路径上的边后,路径上的每一个点所对应的一个连通块 考虑dp,令$f_{S,i}$表示当前1到$n$路径上的最后一个点以及之前点(包括$i$ ...
- AT2657 [ARC078D] Mole and Abandoned Mine
简要题解如下: 记 \(1\) 到 \(n\) 的路径为关键路径. 注意到关键路径只有一条是解题的关键,可以思考这张图长什么样子. 不难发现关键路径上所有边均为桥,因此大致上是关键路径上每个点下面挂了 ...
- 【做题】arc078_f-Mole and Abandoned Mine——状压dp
题意:给出一个\(n\)个结点的联通无向图,每条边都有边权.令删去一条边的费用为这条边的边权.求最小的费用以删去某些边使得结点\(1\)至结点\(n\)有且只有一条路径. \(n \leq 15\) ...
- AtCoder刷题记录
构造题都是神仙题 /kk ARC066C Addition and Subtraction Hard 首先要发现两个性质: 加号右边不会有括号:显然,有括号也可以被删去,答案不变. \(op_i\)和 ...
- AtCoder Regular Contest 078
我好菜啊,ARC注定出不了F系列.要是出了说不定就橙了. C - Splitting Pile 题意:把序列分成左右两部分,使得两边和之差最小. #include<cstdio> #inc ...
- 【AtCoder】ARC078
C - Splitting Pile 枚举从哪里开始分的即可 #include <bits/stdc++.h> #define fi first #define se second #de ...
随机推荐
- day16 匿名函数
# 匿名函数# 函数名 = lambda 参数1,(参数2,....) : 返回值 [注意:匿名函数不允许换行]# 匿名函数返回值和正常函数一样可以是任意数据类型# def add(x,y):# re ...
- vue(七)--监听属性(watch)
1.watch:用来监听每一个属性的变化 2.watch这个对象里面都是函数,函数的名称是data中的属性名称,watch中的函数不需要调用 3.当属性发生改变那么就会触发watch函数,每个函数都会 ...
- 牛客练习赛56 B 小琛和他的学校
题目链接:https://ac.nowcoder.com/acm/contest/3566/B 思路:一条路可把图分为左右两部分. l_ci, l_peo, r_ci, r_peo, w 分别为左边城 ...
- STM32 & RT-Thread的逆向入门
STM32 & RT-Thread的逆向入门 backahasten@0xFA 现在,各种MCU的价格越来越低,同等条件下能买到的ROM和RAM资源也多了.对 ...
- 170.分组-group、permission、user的操作
分组 1.Group.objects.create(group_name):创建分组. 2.group.permissions:某个分组上的权限.多对多关系. (1)group.permissions ...
- fqa0
FQA 0 - Plan 9 简介 0.1 - 什么是 Plan 9 Plan 9 是一个研究操作系统,来自于在 Bell 实验室计算机科学研究中心(CSRC)同样创造了 UNIX 的团队.它出现在2 ...
- LAMP集成环境搭建
本教程是在centos6.8 64位系统下进行操作 我们首先准备搭建LAMP环境 LAMP指的是Linux.Apache.MySQL 和 PHP 如果要安装PHP5.5 需要 首先rpm -ivh h ...
- Python、Django、Celery中文文档分享
1.Python:链接:https://pan.baidu.com/s/12uzxbI-nMkpF7aMa966bTQ 密码:i1x9 2.Django:链接:https://pan.baidu.co ...
- gulp常用插件之wiredep使用
更多gulp常用插件使用请访问:gulp常用插件汇总 wiredep这是一款gulp插件,能够将js.css文件自动插入到html中. 更多使用文档请点击访问wiredep工具官网. Bower是一个 ...
- send and recieve message with myself (python socket )
# socket server import socket sk = socket.socket() sk.bind(("127.0.0.1",8082)) sk.listen() ...