困兽之斗--乐视2017暑期实习生笔试题(二)

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

输入描述:

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



输出描述:

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


输入例子:
dcba
2
0 1
1 2
hellonowcoder
4
0 1
1 4
2 5
2 3

输出例子:
bcda
ehllonowco
方法一:

/******************************************
*@time 2016/08/27   20:58
*@place dhu.13f.5005
*description    并查集+选择排序
***************************************/
#include<cstdio>
#include<cstring>
#include<map>
#include<iostream>
using namespace std;
int Union[10001];
int find_Root(int node)//找到根节点
{
     int tmp=node;
    while(tmp!=Union[tmp])
    {
        tmp=Union[tmp];
    }
    Union[node]=tmp;//此处为优化,缩短查找距离
    return tmp;
}
void creat_Tree(int be,int en)//创建并查集
{
    be=find_Root(be);
    en=find_Root(en);
    if(en!=be)
    {
        if(en>be)
        {
            Union[be]=en;
        }
        else
        Union[en]=be;
    }
}
void init(int num_Of_Nodes)
{
    for(int i=0;i<num_Of_Nodes;i++)
    {
        Union[i]=i;
    }
}
int main()
{
    char str[10001];
    while(scanf(" %s",str)!=EOF)
    {

        int num_Of_Routes;
        scanf("%d",&num_Of_Routes);
        int num_Of_Nodes=strlen(str);
        init(num_Of_Nodes);
        for(int i=0;i<num_Of_Routes;i++)
        {
            int be;
            int en;
            scanf("%d %d",&be,&en);
            creat_Tree(be,en);
        }
        for(int i=0;i<num_Of_Nodes-1;i++)//选择排序
        {
            for(int j=i+1;j<num_Of_Nodes;j++)
            {
                if(find_Root(i)==find_Root(j)&&str[i]>str[j])//如果点在同一棵树中,那么他们就可以交换
                {
                  char t=str[i];
                  str[i]=str[j];
                  str[j]=t;
                }
            }
        }
        printf("%s\n",str);
    }
    return 0;
}


方法二:

/******************************************
*@time 2016/08/27   20:58
*@place dhu.13f.5005
*description    并查集
***************************************/
#include<cstdio>
#include<map>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
int Union[10001];//储存并查集
int find_Root(int node)//找到根节点
{
     int tmp=node;
    while(tmp!=Union[tmp])
    {
        tmp=Union[tmp];
    }
    Union[node]=tmp;//此处为优化,缩短查找距离
    return tmp;
}
void creat_Tree(int be,int en)//创建并查集
{
    be=find_Root(be);
    en=find_Root(en);
    if(be!=en)
    {
        Union[en]=be;
    }
}
void inti(int num_Of_Nodes)//初始化
{
    for(int i=0;i<num_Of_Nodes;i++)
    {
        Union[i]=i;
    }
}
int main()
{
    char str[10001];
    while(scanf(" %s",str)!=EOF)
    {
        int num_Of_Routes;
        scanf("%d",&num_Of_Routes);//彩虹数目

        int num_Of_Nodes=strlen(str);//字符数
        inti(num_Of_Nodes);

        for(int i=0;i<num_Of_Routes;i++)
        {
            int be;
            int en;
            scanf("%d %d",&be,&en);
            creat_Tree(be,en);
        }
        map<int,vector<int> > trees;//将每棵树的所点的下标储存在一个Vector中
        map<int,vector<char> > strs;//将每棵树的所点的内容储存在一个Vector中
        for(int i=0;i<num_Of_Nodes;i++)
        {
            int root=find_Root(i);
            trees[root].push_back(i);
            strs[root].push_back(str[i]);
        }

        for(int i=0;i<trees.size();i++)
        {
            sort(trees[i].begin(),trees[i].end());//排序,使下标从小到大 排列
            sort(strs[i].begin(),strs[i].end());//字符排序
        }
        for(int i=0;i<trees.size();i++)//将排行序的字符插入到字符串中
        {
            for(int j=0;j<trees[i].size();j++)
            {
                str[trees[i][j]]=strs[i][j];
            }
        }
        printf("%s\n",str);
    }
}






發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章