美文网首页
HDU——1116 Play on words

HDU——1116 Play on words

作者: 四川孙一峰 | 来源:发表于2017-01-15 19:02 被阅读0次

    题目大意

    这个题让我们求给出的几个字符串是否能全部首尾相连,字符串长度至少为2,其连接方式类似于成语接龙,需要一个字符串的尾巴与第二个字符串开头相同。

    样例输入

    3
    2
    acm
    ibm
    3
    acm
    malform
    mouse
    2
    ok
    ok

    样例输出

    The door cannot be opened.
    Ordering is possible.
    The door cannot be opened.

    题目分析

    这题是个欧拉回路和并查集的结合。因为我是菜鸟还不是很懂欧拉回路就不在此赘述,日后理解后再详细写。
    先说说我的想法:
    1.将每个输入的字符串的首字母与尾字母的入度和出度分别加一,分别放在in[]与out[]数组中。并记录出现过的字母(只记录首位)。

    2.判定其是否满足题目所给的条件相连即只有一个字母入度减出度为1,一个字母入度减出度为-1,剩下的入度减去出度都为0。若不满足直接退出。

    3.剩下的就判断其是否有连通性,我使用并查集的时候将father数组的根节点位置记录为他节点的个数并以负数表示。然后每输入一个字符串将首尾字母合并,而若是首尾字母相同,则不合并。这样若形成的是链而不是环的话,father数组中最小的值(因为是负数)就与输入的字符串首尾字母出现的个数相同。
    若相同则判断可行,反之不行。

    (好吧可能我的叙述方式有点问题,还是把代码贴出来,讲道理代码也丑)

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<iostream>
    using namespace std;
    int pre[30];
    int in[30],out[30],n,ans[30];// ans用来记录in与out相减的值。
    char word[1010];
    int judge[30];  //判断字母是否出现过,出现过为1,否则为0。
    
    int Find(int x)
    {
        if(pre[x] < 0) return x;
        return pre[x] = Find(pre[x]);
    }
    
    int Union(int R1 , int R2)
    {
        int r1 = Find(R1) , r2 = Find(R2);
        int temp = pre[r1] + pre[r2];
        if(pre[r1] > pre[r2])
        {
            pre[r1] = r2; pre[r2] = temp;
        }
        else
        {
            pre[r2] = r1 ; pre[r1] = temp;
        }
    }
    
    int main()
    {
        int t;
        scanf("%d",&t);
        while(t--)
        {
            memset(in,0,sizeof(in));
            memset(out,0,sizeof(out));
            memset(word,0,sizeof(word));
            memset(judge,0,sizeof(judge));
            memset(pre,-1,sizeof(pre));
            scanf("%d",&n);
            for(int i = 1 ; i <= n ;i++)
            {
                scanf("%s",word);
                int len = strlen(word);
                judge[word[0]-'a'+1]=1 ;
                judge[word[len-1]-'a'+1]=1;//将首尾字母记录为出现过。
    
                in[word[0]-'a'+1]++;
                out[word[len-1]-'a'+1]++;
                if(Find(word[0]-'a'+1) != Find(word[len-1]-'a'+1))
                {
                    Union(word[0]-'a'+1,word[len-1]-'a'+1);   //若首尾字母不同则合并。
                }
            }
            for(int i = 0 ; i < 30 ; i++)
            {
                ans[i] = in[i] - out[i];         //将所有字母入度和出度的值记录下来。
            }
            int co1 = 0 , co2 = 0 , flag = 1;
            for(int i = 0 ; i < 30 ; i++)        //从这里开始判断是否只有一个-1,一个1,其余全为0的情况。
            {
                if(ans[i]!=0&&ans[i]!=-1&&ans[i]!=1)
                {
                    flag = 0;
                    break;
                }
                if(ans[i]==-1)
                {
                    co1++;
                    if(co1 > 1)
                    {
                        flag = 0;
                        break;
                    }
                }
                if(ans[i]==1)
                {
                    co2++;
                    if(co2>1)
                    {
                        flag = 0; break;
                    }
                }
            }
            if(flag == 0)                          //不满足则退出
            {
                printf("The door cannot be opened.\n"); continue;
            }
            int con = 0;
            for(int i = 0 ; i < 30  ; i++)          //记录出现过字母的个数 。
            {
                if(judge[i]) con++;
            }
            flag = 0;
            for(int i = 0 ; i < 30 ; i++)            //判断与最长链的节点个数是否相等。
            {
                 if(pre[i]==(-1)*con)
                 {
                     flag = 1;break;
                 }
            }
            if(flag == 1) printf("Ordering is possible.\n");
            else printf("The door cannot be opened.\n");
    
    
        }
    }
    
    

    相关文章

      网友评论

          本文标题:HDU——1116 Play on words

          本文链接:https://www.haomeiwen.com/subject/lxfubttx.html