专栏文章

CF1303C Perfect Keyboard 题解

CF1303C题解参与者 2已保存评论 1

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
1 条
当前快照
1 份
快照标识符
@mip6aol3
此快照首次捕获于
2025/12/03 06:52
3 个月前
此快照最后确认于
2025/12/03 06:52
3 个月前
查看原文

CF1303C Perfect Keyboard

我近期在狂刷 CF,好久没写题解了,今天来一发。

思路

通过观察,键盘上每一个字母最多只与两个字母相邻,所以当一个字母与两个以上的不同字母相邻时肯定是无解的,直接输出 NO
接下来我们进行模拟。因为字母只有 2626 个,所以我们可以用邻接矩阵来存储相邻的字母,并使用桶来计算每个字母相邻不同字母的数量。
接下来,我们将每个相邻字母数小于 22 个的字母且没有被访问过的字母跑 DFS,将访问到的字母放进答案中。
为什么是小于 22 个?我们不妨先考虑一组特殊数据:afghjfg。这组数据肯定是无解的,因为其中有环。环中字母的相邻字母数一定不小于 22 个,所以环内的字母无法被访问,可以由此来判断出现环的无解情况。
综上,本题大致思路已经完成。

代码

多组数据,记得清空。

预处理部分

CPP
for (int i = 1; i < n; i++)
{
    if (!g[s[i]][s[i - 1]])                           // 防止重复计算!
    {
        g[s[i]][s[i - 1]] = 1, g[s[i - 1]][s[i]] = 1; // g[u][v]: 是否存在 (u, v) 边
        lk[s[i]]++, lk[s[i - 1]]++;                   // 双向边
        if (lk[s[i]] > 2 || lk[s[i - 1]] > 2)         // lk[i]: 字母 i 的相邻字母数
        {
            cout << "NO\n";
            print = true;
            break;
        }
    }
}

DFS 部分

CPP
void dfs(char u)
{
    if (vis[u])
        return ;
    vis[u] = true;                   // 记录是否访问
    ans += u;                        // ans: 构造结果
    for (int v = 'a'; v <= 'z'; v++)
        if (g[u][v] && v != u)       // g[u][v]: 是否存在 (u, v) 边
            dfs(v);
}

主函数核心部分

CPP
for (int i = 'a'; i <= 'z'; i++)
    if (!vis[i] && lk[i] <= 1)
        dfs(i);
for (int i = 'a'; i <= 'z'; i++)
{
    if (!vis[i]) // 有字母没访问,一定存在环
    {
        cout << "NO\n";
        print = true;
        break;
    }
}

评论

1 条评论,欢迎与作者交流。

正在加载评论...