zoukankan      html  css  js  c++  java
  • CF1383C String Transformation 2 题解

    Codeforces
    Luogu

    Description.

    每次选出若干相同字符,变成另一种相同字符。
    问从 \(S\) 至少几步变成 \(T\)

    Solution.

    首先很显然建图,注意每条边是有时间的
    然后就错了!忘记考虑时间了,大小为 \(n\) 的完全有向图需要 \(2\cdot n-2\) 步而不是 \(n\)
    首先,如果完全不联通,贡献显然可以分开考虑,我们需要求出弱联通图答案。
    然后发现不会做,先手模出一些特殊情况。(设弱联通图点数为 \(n\)


    考虑一个普通图,它的答案肯定不大于 \(2n-2\),构造如下。

    • \(1\rightarrow 2\rightarrow 3\rightarrow\dots\rightarrow n\)
    • \(n\rightarrow 1\rightarrow\dots\rightarrow n-1\)

    \(\forall (i,j)\in G\),如果 \(i< j\) 通过上面的肯定可达,否则先走到 \(n\) 再通过下面的就可达。


    弱联通图的答案下界肯定是 \(n-1\),因为它至少要联通。
    一个 DAG 答案是 \(n-1\),因为按一个拓扑序来排列即可,而且这个答案是理论下界。
    那我们对于一张不是 DAG 的图,把一个 DAG 按照上面压缩后肯定答案不会变差。


    考虑这样一个结论,对于一个点,不在最大导出 DAG 上的点一定与导出 DAG 相邻。
    设导出 DAG 点集为 \(S\),则 \(\forall x\not\in S,\exists u,v\in S,(u,x),(x,v)\in G\)\(v\) 可达 \(u\)
    所以我们必须要把这两条边全都涂上,也就是说我们需要 \(2\) 的代价对剩下所有的点连边。
    然后直接搞即可。

    不难(hui)证明这个也是最优的。

    Coding.

    点击查看大傻逼代码
    //是啊,你就是那只鬼了,所以被你碰到以后,就轮到我变成鬼了{{{
    #include<bits/stdc++.h>
    using namespace std;typedef long long ll;
    template<typename T>inline void read(T &x)
    {
    	x=0;char c=getchar(),f=0;
    	for(;c<48||c>57;c=getchar()) if(!(c^45)) f=1;
    	for(;c>=48&&c<=57;c=getchar()) x=(x<<1)+(x<<3)+(c^48);
    	f?x=-x:x;
    }
    template<typename T,typename...L>inline void read(T &x,L&...l) {read(x),read(l...);}/*}}}*/
    int n=20,m,mp[21],fa[21],F[1<<20];char S[100005],T[100005];
    inline int getf(int x) {return fa[x]==x?x:fa[x]=getf(fa[x]);}
    inline void mrg(int x,int y) {x=getf(x),y=getf(y);if(x^y) fa[x]=y;}
    inline int count(int x) {int r=0;for(int i=0;i<n;i++) r+=(x>>i)&1;return r;}
    inline char dfs(int S)
    {
    	if(~F[S]) return F[S];else if(!S) return F[S]=1;else F[S]=0;
    	for(int i=0;i<n;i++) if((S>>i)&1&&!(mp[i]&S)) F[S]|=dfs(S^(1<<i));
    	return F[S];
    }
    inline void solve()
    {
    	read(m),scanf("%s%s",S+1,T+1);for(int i=0;i<n;i++) fa[i]=i,mp[i]=0;
    	for(int i=1;i<=m;i++) if(S[i]^T[i]) mp[S[i]-'a']|=1<<(T[i]-'a'),mrg(S[i]-'a',T[i]-'a');
    	int rs=n*2;memset(F,-1,sizeof(F));for(int i=0;i<n;i++) rs-=getf(i)==i;
    	int mx=0;for(int i=0;i<(1<<n);i++) if(dfs(i)) mx=max(mx,count(i));
    	printf("%d\n",rs-mx);
    }
    int main() {int Ca;for(read(Ca);Ca--;) solve();return 0;}
    
  • 相关阅读:
    MathType如何插入竖直线
    MongoDB时间类型
    《穆斯林的葬礼》读书笔记
    Fluentd安装——通过rpm方式
    MongoDB安装、管理工具、操作
    Flask服务入门案例
    python判断类型
    linux硬链接与软链接
    python 环境问题
    Linux进程管理工具——supervisor
  • 原文地址:https://www.cnblogs.com/pealfrog/p/15178560.html
Copyright © 2011-2022 走看看