A. String Transformation 1

本文探讨了一种将字符串转换问题转化为图论问题的方法。通过建立字符串不同字符之间的边,判断无解条件并采用拓扑排序策略,计算最少转换步骤。在C++代码实现中,展示了如何遍历图的连通块以确定所需操作次数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

做好当前吧,抱怨和祈求怜悯没有任何作用,你不是来作秀的!

题目地址

又是一道好的题目(其实是因为我菜。。),cf 真的是个好东西。

思路:
首先先判断无解的情况:这个很好的判断。
然后是有解的思路:看成一个图论的问题,我们将字符串 a a a和字符串 b b b不相同的点之间建一条边,我们可以想一下假设我们需要 a [ i ] − > b [ i ] , a [ j ] − > b [ j ] a[i] ->b[i], a[j] -> b[j] a[i]>b[i],a[j]>b[j],并且我们如果 b [ j ] = = b [ i ] b[j] == b[i] b[j]==b[i],那么我们就可以考虑先将 a [ i ] − > a [ j ] ( a [ i ] < a [ j ] ) a[i] - > a[j] (a[i] <a[j]) a[i]>a[j](a[i]<a[j]),这样做的话我们就可以顺带的将图中 a [ i ] − > a [ j ] a[i] -> a[j] a[i]>a[j]的边完成并且不需要消耗多余的步数,我们发现这样是拓扑序,即:处在前边的点都可以向后边进行延伸,我们每次向这个拓扑序中加一个点都需要最小耗费一个步数,加入的点可以按照字典序进行连边,当然在图中我们可能存在所有的点不在一个联通块的情况,所以我们需要判断一下,假设我们只有一个连通块,那么我只需要加入 ( n − 1 ) (n - 1) (n1)次边,假设我们有两个连通块那么我们就需要加入 ( n − 2 ) (n - 2) (n2)条边,以此类推。

#include <iostream>
#include <cstring>
#include <sstream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <cstdio>

using namespace std;

const int N = 20;
int a, b, c;
int map[N][N];
bool vis[N];
void dfs (int u)
{
    vis[u] = true;
    for (int i = 0; i < 20; i ++)
        if (map[u][i] && !vis[i]) dfs (i);
}
int main()
{
    int T; scanf ("%d", &T);
    while (T --)
    {
        int n; string a, b; cin >> n >> a >> b;
        memset (vis, 0, sizeof vis);
        memset (map, 0, sizeof map);
        bool flag = true;
        for (int i = 0; i < n; i ++) // have a 
            if (a[i] > b[i]) flag = false;
            else map[a[i] - 'a'][b[i] - 'a'] = true, map[b[i] - 'a'][a[i] - 'a'] = true;
        if (!flag)
        {
            puts ("-1");
            continue;
        }
        int res = 20;
        for (int i = 0; i < 20; i ++) 
            if (!vis[i]) dfs (i), res --; 
        printf ("%d\n", res);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值