牛客网-并查集(交换位置)

来源:互联网 发布:淘宝新店有扶持吗 编辑:程序博客网 时间:2024/06/10 11:59

题目:

经过深思熟虑之后,小贱君打算去M国闯一闯,那是一个古老的东方国度,传说有很多高阶魔法师,他想成为一名伟大的魔法师,将来征服星辰大海。
经过千辛万苦,小贱君终于来到了M国,不幸的是刚进城门小贱君就被M国的守城士兵困在了一种叫做“困兽之斗”的阵法之中。
士兵对小贱君说:“看到漂浮在你身边的宝石了吗?彩虹连接的两颗宝石可以任意交换位置,你需要通过一系列交换后使得宝石组成的字符串的字典序最小。若不能破阵,那还是请回吧!”
小贱君观察了一下周围的宝石,只见每颗宝石上标有一个小写字母,而且有一些宝石上通过彩虹与其他宝石相连。
琢磨了半天,他终于搞懂了这个阵法的意思:
若宝石系列为:dcba
其中有两道彩虹,分别是(0,1),(1,2),代表第一个位置上的宝石可以和第二个位置上的宝石互换,第二个位置上的宝石可以和第三个位置上的宝石互换,最终可以得到字典序最小的宝石系列:bcda。
作为小贱君的死党,你有什么方法帮助他破阵吗?

输入描述:

输入包含多组测试数据。对于每组测试数据:字符串s --- 代表宝石序列n --- 代表有n条彩虹接下来n行,每行两个数ai,bi --- 表示ai和bi由一条彩虹相连。保证:1<=s的长度<=100001<=n<=10000且输入数据均合法。



输出描述:

对于每组数据,输出一个字符串


输入例子:
dcba20 11 2hellonowcoder40 11 42 52 3

输出例子:
bcdaehllonowcoder
这道题主要是找到所有的可以交换位置的集合,最好的办法是利用并查集的思想:

#include<iostream>#include<vector>#include<list>#include<fstream>#include<string>#include<set>#include<map>#include<algorithm>#include<stack>using namespace std;#define N 20int pre[N];int find(int x){int r = x;while (r != pre[r])r = pre[r];//x的最终根节点为rreturn r;}void merge(int a, int b){int fa, fb;fa = find(a);fb = find(b);if (fa == fb) return;//两个的父节点不相等pre[fb] = fa;}void init(){for (int i = 0; i < N; i++)pre[i] = i;//刚开始的时候每个数的上一级是自己}int main(){ifstream fin("C:\\Users\\caoyan\\Desktop\\data.txt");int num, head, next;fin >> num;init();while (num){fin >> head;fin >> next;merge(head, next);num--;}for (int h = 0; h < N; h++){//元素个数int father = find(h), j, tmp = h;while (tmp != father){//只要i的每上一层父节点和最终根节点不等j = pre[tmp];//先把k的当前father保存起来pre[tmp] = father;//然后把k的father设置为最后的根节点tmp = j;}}return 0;}


0 0
原创粉丝点击