Codeforces 939D - Love Rescue

news/2024/7/4 13:32:18

传送门:http://codeforces.com/contest/939/problem/D

本题是一个数据结构问题——并查集(Disjoint Set)。

给出两个长度相同,且仅由小写字母组成的字符串S=s[1..n]、T=t[1..n]。已知一个无序对(u,v)可以完成任意次的以下转换操作:u→vv→u。求将字符串S转换为T所需要的最少的无序对的数目,并打印出相应可行的方案下的所有无序对。

首先构造一张无向图G=<V,E>,表示S→T的状态转换图:结点集V={‘a’,’b’,’c’,...,’z’};边集E={(si,ti)|si≠ti,i=1,2,...,n}。对于这张图的连通分量,构造一个边集最小的连通图——即无向图的生成树。可以采用简化的Kruskal算法求这棵生成树。

实际上,这是一个并查集的问题。通过并查集,对于每一个i,判断siti是否在同一个集合中:若二者不在同一个集合中,则合并二者所在的集合。参考程序如下:

#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#define MAX_V 26
#define MAX_N 100005

char s[MAX_N], t[MAX_N];
char uset[MAX_V], vset[MAX_V];

//Disjoint Set
int pa[MAX_V];
int rank[MAX_V];

void init(int n)
{
    memset(pa, 0, sizeof(pa));
    memset(rank, 0, sizeof(rank));
    for (int i = 0; i < n; i++) {
        pa[i] = i;
        rank[i] = 0;
    }
}

int find(int x)
{
    if (pa[x] == x) return x;
    else return pa[x] = find(pa[x]);
}

void unite(int x, int y)
{
    x = find(x);
    y = find(y);
    if (x == y) return;
    if (rank[x] < rank[y]) pa[x] = y;
    else {
        pa[y] = x;
        if (rank[x] == rank[y]) rank[x]++;
    }
}

bool same(int x, int y)
{
    return find(x) == find(y);
}

int main(void)
{
    int n;
    scanf("%d", &n);
    scanf("%s", s);
    scanf("%s", t);
    int cnt = 0;
    init(MAX_V);
    for (int i = 0; i < n; i++) {
        if (s[i] != t[i]) {
            int u = s[i] - 'a';
            int v = t[i] - 'a';
            if (!same(u, v)) {
                unite(u, v);
                uset[cnt] = u + 'a';
                vset[cnt] = v + 'a';
                cnt++;
            }
        }
    }
    printf("%d\n", cnt);
    for (int i = 0; i < cnt; i++)
        printf("%c %c\n", uset[i], vset[i]);
    return 0;
}

 

转载于:https://www.cnblogs.com/siuginhung/p/8452654.html


http://www.niftyadmin.cn/n/4141105.html

相关文章

今天聊发兴致,写了一个 COM STEP BY STEP,结果。。。

太久没写C程序了&#xff0c;都忘记class声明后面的;号了&#xff0c;唉。。。。转载于:https://www.cnblogs.com/xiaotaoliang/archive/2005/07/20/196230.html

统计子目录大小情况并排序显示

http://blog.chinaunix.net/u/6542/showart.php?id394070使用 du -sh * 可以显示指定目录下各文件&#xff0f;目录的大小情况&#xff0c;但是输出结果不够人性化(human-readable)&#xff0c;以 /usr/share/目录为例du -sh /usr/share/* 会输出如下信息654K /usr/share/a…

鼠标相关API应用

我们在编制应用软件的过程中&#xff0c;常常需要对光标和鼠标操作&#xff0c;本人在文中介绍了Windows系统中有关实现对鼠标和光标进行操作的API函数&#xff0c;并给出了在Visual C6.0中利用所介绍的API函数实现对鼠标和光标的操作的代码。一、隐藏和显示光标函数&#xff1…

11.6 MariaDB安装 11.7/11.8/11.9 Apache安装

[rootlizhipenglinux01 mariadb]# cp support-files/my-small.cnf /usr/local/mariadb/my.conf 配置文件[rootlizhipenglinux01 mariadb]# cp support-files/mysql.server /etc/init.d/mariadb 启动脚本[rootlizhipenglinux01 mariadb]# vim /usr/l…

C语言之函数指针

C语言之函数指针 在C/C中&#xff0c;数据指针是最直接&#xff0c;也最常用的&#xff0c;因此&#xff0c;理解起来也比较容易。而函数指针&#xff0c;作为运行时动态调用&#xff08;比如回调函数 CallBack Function&#xff09;是一种常见的&#xff0c;而且是很好用的手段…

Android:Animation

Android 之 Animation 关于动画的实现&#xff0c;Android提供了Animation&#xff0c;在Android SDK介绍了2种Animation模式&#xff1a;1. Tween Animation&#xff1a;通过对场景里的对象不断做图像变换(平移、缩放、旋转)产生动画效果&#xff0c;即是一种渐变动画&#xf…

如何高效的编写Verilog HDL——进阶版

博主之前写过一篇文章来谈论如何高效的编写Verlog HDL——菜鸟版&#xff0c;在其中主要强调了使用Notepad来编写Verilog HDL语言的便捷性&#xff0c;为什么说是菜鸟版呢&#xff0c;因为对于新手来说&#xff0c;在还没有熟悉软件和硬件描述语言的时候&#xff0c;使用Notepa…

电脑网络最基本的常识简介(合集)

电脑网络最基本的常识简介 什么是HTML? HTML(Hyper Text Mark-up Language )即超文本标记语言&#xff0c;是 WWW 的描述语言&#xff0c;由 Tim Berners-lee提出。设计 HTML 语言的目的是为了能把存放在一台电脑中的文本或图形与另一台电脑中的文本或图形方便地联系在一起&a…