Codeforces 1383C - String Transformation 2(找性质+状压 dp)
神奇的强迫症效应,一场只要 AC 了 A、B、D、E、F,就一定会把 C 补掉(
感觉这个 C 难度比 D 难度高啊……
首先考虑对问题进行初步转化。显然对于 \(s_i=s_j,t_i=t_j\) 的 \((i,j)\),我们肯定会将它们放在一起操作,这启发我们将所有 \((s_i,t_i)\) 看作一个二元组,那么如果我们把“每一步将字符 \(x\) 变为 \(y\)”这样的操作视作一条从 \(x\) 连向 \(y\),权值为当前是第几次操作。那么一个连边方式合法,当且仅当对于所有二元组 \((s,t)\) 都存在一条 \(s\to t\) 的路径,满足其经过的所有边的权值单调递增。
考虑怎样解决这个问题,首先注意到 \(39\) 次操作一定是可行的,具体来说就 \(’a’\to’b’\to’c’\to\cdots\to’t’\to’a’\to\cdots’t’\) 连两个环,这样一定能保证对于所有 \((x,y)\) 都存在符合要求的路径,不过注意到我们并不一定要所有 \((x,y)\) 之间都存在符合要求的路径,因此考虑从这个角度入手减少操作次数。这里直接给出结论:如果我们设 \(n=20\) 表示图中的点数,对于所有二元组 \(s\to t\) 我们再建一张图 \(G\),并设 \(S\) 表示满足 \(S\subseteq G\),\(S\) 为 DAG 且 \(S\) 包含的点数最多的导出子图,\(c\) 表示 \(G\) 中弱连通块的个数,那么 \(res=2n-S\) 中点的个数 \(-c\)。
证明:首先我们来说明我们能达到这张图,我们考察 \(G\) 中每一个弱连通块,显然它有一部分点是包含在 \(S\) 当中的对吧,对于这部分点我们将它们按拓扑序编号 \(1,2,3,\cdots,k\),其中 \(k\) 表示该连通块中包含在 \(S\) 中的点数,对于剩余的点我们随意编号 \(k+1,k+2,\cdots,m\),那么我们考虑这样连边:\(k\to k+1\to k+2\to\cdots\to m\to 1\to 2\to\cdots\to k\to k+1\to k+2\to\cdots m\),这样总边数显然是 \(2m-k-1\),不难发现这样一来,该连通块中只有 DAG 中拓扑序从后往前的二元组无法到达,而由于这是一个 DAG,因此这样的点之间没有边,符合要求,把它们的贡献累加起来就是 \(2n-S\) 中点的个数 \(-c\)。
接下来来说明这就是本题操作次数的下界。我们不妨想象这样一个在一个初始没有边的图中加边的过程,每加入一条边有两种可能,要么沟通了原本不在同一个弱连通块中的两点,由最终得到的图中恰有 \(c\) 个连通块可知这样的边至少有 \(n-c\) 条,要么连接了两个原本就在同一连通块中的边,对于这样的边我们维护一个 \(T\) 表示当前无法沿着一个合法的路径到达本身的点集,那么显然初始 \(T=\{1,2,3\cdots,n\}\),而当我们加入 \((x,y)\) 这条边时,最多使 \(y\) 这个点能够到达本身,即 \(T\) 的大小最多减 \(1\),因此如果最终 \(|T|=x\),那么操作次数 \(\ge n-c+n-x\),又显然最终 \(T\) 中的点必须形成一个 DAG,否则其中必然存在圈 \(x_1\to x_2\to\cdots\to x_k\to x_1\),由于这些边必须可达,因此可以推出 \(x_1\) 可以到达 \(x_1\),与 \(T\) 的定义矛盾。因此最终 \(x\le\) 上文中 \(S\) 的点数,也就证明了答案的下界。据说这方法有个名字叫势能法?反正总之很神仙就对了(
有了这个性质之后题目就很容易了。\(n,c\) 都很容易求得。至于怎样求 \(S\) 的大小……注意到这题最多涉及到 \(20\) 个字母,即点数最多 \(20\),一脸状压,直接枚举 \(S\) 的点集并 check 是 \(2^{20}20^2\) 的,不知道能不能通过。考虑加点《小优化》,我们设 \(dp_S\) 表示 \(S\) 的导出子图是否是一个 DAG,那么我们考虑每次增加一个点 \(x\) 作为 DAG 中出度为 \(0\) 的点并检验这个点连出去的边中,是否有边指向 \(S\) 中的点,如果有那么 \(dp_{S\cup\{x\}}=0\),否则 \(dp_{S\cup\{x\}}=1\),这样是 \(2^{20}·20\) 的,可以通过。
const int ALPHA=20;
const int MAXN=1e5;
const int MAXP=1048576;
int n,f[ALPHA+2],fr[ALPHA+2];
char s[MAXN+5],t[MAXN+5];
bool dp[MAXP+5];
void clear(){memset(f,-1,sizeof(f));memset(fr,0,sizeof(fr));memset(dp,0,sizeof(dp));}
int find(int x){return (!~f[x])?x:f[x]=find(f[x]);}
void merge(int x,int y){x=find(x);y=find(y);if(x^y) f[x]=y;}
void solve(){
scanf("%d%s%s",&n,s+1,t+1);clear();
for(int i=1;i<=n;i++){
int x=s[i]-'a',y=t[i]-'a';
fr[x]|=(1<<y);merge(x,y);
} int res=ALPHA<<1,mx=0;
for(int i=0;i<ALPHA;i++) if(find(i)==i) res--;
dp[0]=1;for(int i=0;i<MAXP;i++) if(dp[i]){
chkmax(mx,__builtin_popcount(i));
for(int j=0;j<ALPHA;j++) if(~i>>j&1){
if((fr[j]&i)==0) dp[i|(1<<j)]=1;
}
} printf("%d\n",res-mx);
}
int main(){
int qu;scanf("%d",&qu);
while(qu--) solve();
return 0;
}
Codeforces 1383C - String Transformation 2(找性质+状压 dp)的更多相关文章
- 没有找零 状压dp
没有找零 状压dp 约翰到商场购物,他的钱包里有K(1 <= K <= 16)个硬币,面值的范围是1..100,000,000.约翰想按顺序买 N个物品(1 <= N <= 1 ...
- Codeforces 1225G - To Make 1(bitset+状压 dp+找性质)
Codeforces 题目传送门 & 洛谷题目传送门 还是做题做太少了啊--碰到这种题一点感觉都没有-- 首先我们来证明一件事情,那就是存在一种合并方式 \(\Leftrightarrow\) ...
- Codeforces Gym 100610 Problem K. Kitchen Robot 状压DP
Problem K. Kitchen Robot Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/10061 ...
- Educational Codeforces Round 13 E. Another Sith Tournament 状压dp
E. Another Sith Tournament 题目连接: http://www.codeforces.com/contest/678/problem/E Description The rul ...
- [BZOJ3312][USACO]不找零(状压DP)
Description 约翰带着 N 头奶牛在超市买东西,现在他们正在排队付钱,排在第 i 个位置的奶牛需要支付 Ci元.今天说好所有东西都是约翰请客的,但直到付账的时候,约翰才意识到自己没带钱,身上 ...
- CF1103D Codeforces Round #534 (Div. 1) Professional layer 状压 DP
题目传送门 https://codeforces.com/contest/1103/problem/D 题解 失去信仰的低水平选手的看题解的心路历程. 一开始看题目以为是选出一些数,每个数可以除掉一个 ...
- FZU 2093 找兔子 状压DP
题目链接:找兔子 n的范围是[1, 15],可以用0 到 (1<<n)-1 的数表示全部状态,用dp[i] = t表示到达状态i的最少时间是t,对于每个点,如果它能到达的所有点在t秒时都已 ...
- Codeforces 279D The Minimum Number of Variables 状压dp
The Minimum Number of Variables 我们定义dp[ i ][ mask ]表示是否存在 处理完前 i 个a, b中存者 a存在的状态是mask 的情况. 然后用sosdp处 ...
- codeforces#580 D. Kefa and Dishes(状压dp)
题意:有n个菜,每个菜有个兴奋值,并且如果吃饭第i个菜立即吃第j个菜,那么兴奋值加ma[i][j],求吃m个菜的最大兴奋值,(n<=18) 分析:定义dp[status][last],statu ...
随机推荐
- Framework - 性能统计
摘要 近期对接客户时,客户方希望提供 SDK 的性能.内存.隐私支持等一些数据,所以就对 SDK 进行了一些性能测试. 在用表格统计整理这些数据时,突然发现,经常用统计的方式看 SDK 的相关数据,似 ...
- ShardingSphere学习
1 基本概念 1.1 ShardingSphere概述 官网:https://shardingsphere.apache.org/index_zh.html 1.2 分库分表概述 分库分表是为了解决由 ...
- mall笔记
介绍 SpringBoot.SpringCloud.SpringCloudAlibaba.Nacos.Sentinel.Seata整合demo. 软件架构 JDK 1.8 Spring Boot 2. ...
- Linux搭建SVN服务器详细教程
前言 本文讲解Linux系统下如何搭建SVN服务器,详细说明各配置项的功能,最终实现可管控多个项目的复杂配置. SVN是subversion的缩写,是一个开放源代码的版本控制系统,通过采用分支管理系统 ...
- 微信小程序的支付流程
一.前言 微信小程序为电商类小程序,提供了非常完善.优秀.安全的支付功能 在小程序内可调用微信的API完成支付功能,方便.快捷 场景如下图所示: 用户通过分享或扫描二维码进入商户小程序,用户选择购买, ...
- DevOps 时代的高效测试之路
10 月 22 日,2021 届 DevOps 国际峰会在北京顺利召开,来自国内外的顶级技术专家共同畅谈 DevOps 体系与方法.过程与实践.工具与技术.CODING 测试及研发流程管理产品总监程胜 ...
- Convolutional Neural Network-week1编程题(一步步搭建CNN模型)
Convolutional Neural Networks: Step by Step implement convolutional (CONV) and pooling (POOL) layers ...
- BUAA软工-结对项目
BUAA2020 软件工程-结对项目 Author:17373015 乔玺华 学号 cnblog profile 17373260(本文作者) Prime21 17373015(结对队友) ...
- seata代码控制回滚和临时挂起分布式事物
seata代码控制回滚和临时挂起分布式事物 一.说明 二.功能实现 1.手动回滚分布式事物 2.临时挂起分布式事物 三.完整代码 四 参考链接 一.说明 此处只是简单的记录一下,使用了 Seata后, ...
- linux hostid与lmhostid
https://wangchujiang.com/linux-command/c/hostid.html hostid(host identifier) 显示当前主机的十六进制数字标识. 概要 hos ...