• POJ 1386 Play on Words


    Play on Words
    Time Limit: 1000MS   Memory Limit: 10000K
    Total Submissions: 7970   Accepted: 2802

    Description

    Some of the secret doors contain a very interesting word puzzle. The team of archaeologists has to solve it to open that doors. Because there is no other way to open the doors, the puzzle is very important for us. 

    There is a large number of magnetic plates on every door. Every plate has one word written on it. The plates must be arranged into a sequence in such a way that every word begins with the same letter as the previous word ends. For example, the word ``acm'' can be followed by the word ``motorola''. Your task is to write a computer program that will read the list of words and determine whether it is possible to arrange all of the plates in a sequence (according to the given rule) and consequently to open the door. 

    Input

    The input consists of T test cases. The number of them (T) is given on the first line of the input file. Each test case begins with a line containing a single integer number Nthat indicates the number of plates (1 <= N <= 100000). Then exactly Nlines follow, each containing a single word. Each word contains at least two and at most 1000 lowercase characters, that means only letters 'a' through 'z' will appear in the word. The same word may appear several times in the list.

    Output

    Your program has to determine whether it is possible to arrange all the plates in a sequence such that the first letter of each word is equal to the last letter of the previous word. All the plates from the list must be used, each exactly once. The words mentioned several times must be used that number of times. 
    If there exists such an ordering of plates, your program should print the sentence "Ordering is possible.". Otherwise, output the sentence "The door cannot be opened.". 

    Sample Input

    3
    2
    acm
    ibm
    3
    acm
    malform
    mouse
    2
    ok
    ok
    

    Sample Output

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

    Source

     
     
    题意 :N个盘子,每个盘子上写着一个仅由小写字母组成的英文单词。你需要给这些盘子安排一个合适的顺序,使得相邻两个盘子中,前一个盘子上面单词的末字母等于后一个盘子上面单词的首字母。请你编写一个程序,判断是否能达到这一要求。

    思路:这道题,有一个很巧妙的转换,把点变成边。以26个字母作为顶点;对于每一个盘子,如果它的首字母为c1,末字母为c2,那么从c1向c2连一条有向边。如下图。然后判断图连通,再判断它是否为欧拉图 PS:因为有重边,用边表建图时(在建图时加判断 用边表也可以),会超时,用邻接矩形比较好 因为只有26个点。


    poj <wbr>1386 <wbr>Play <wbr>on <wbr>Words(欧拉回路+dfs)
     
     
    通过图(无向图有向图)中所有边一次且仅一次行遍图中所有顶点的通路称为欧拉通路,通过图中所有边一次且仅一次行遍所有顶点的回路称为欧拉回路。具有欧拉回路的图称为欧拉图(Euler Graph),具有欧拉通路而无欧拉回路的图称为半欧拉图
     
    欧拉图
    h 欧拉通路(回路)与欧拉图 通过图G的每条边一次且仅一次,而且走遍每个结点的通路(回路),就是欧拉通路(回路). 存在欧拉回路的图就是欧拉图.
    欧拉回路要求边不能重复,结点可以重复. 笔不离开纸,不重复地走完所有的边,且走过所有结点,就是所谓的一笔画.
    h欧拉图或通路的判定
    (1) 无向连通图G是欧拉图ÛG不含奇数度结点(G的所有结点度数为偶数):(定理1)
    (2) 非平凡连通图G含有欧拉通路ÛG最多有两个奇数度的结点;(定理1的推论)
    (3) 连通有向图D含有有向欧拉回路(即欧拉图)ÛD中每个结点的入度=出度
    连通有向图D含有有向欧拉通路ÛD中除两个结点外,其余每个结点的入度=出度,且此两点满足deg-(u)-deg+(v)=±1. (定理2)
    欧拉图是普通逻辑学中的重点之一,图论的一部分,可以直观的表示概念间的关系,刑事侦查逻辑里有实际用途.


    欧拉回路+并查集:
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    
    using namespace std;
    
    const int VM=27;
    
    int indeg[VM],outdeg[VM],father[VM];
    int vis[VM];
    
    int findSet(int x){
        if(x!=father[x]){
            father[x]=findSet(father[x]);
        }
        return father[x];
    }
    
    int abs(int x){
        return x<0?-x:x;
    }
    
    bool Judge(){   //判断是否为欧拉图
        int sum1=0,sum2=0,sum3=0;
        for(int i=0;i<26;i++){
            if(vis[i] && father[i]==i)  //祖先有多少个
                sum2++;
            if(abs(indeg[i]-outdeg[i])==1)
                sum1++;
            else if(indeg[i]!=outdeg[i])
                sum3++;
        }
        if(sum3>0 || sum1>2 || sum2>1)
            return 0;
        return 1;
    }
    
    int main(){
    
        //freopen("input.txt","r",stdin);
    
        char str[1010];
        int t,n;
        scanf("%d",&t);
        while(t--){
            scanf("%d",&n);
            memset(indeg,0,sizeof(indeg));
            memset(outdeg,0,sizeof(outdeg));
            memset(vis,0,sizeof(vis));
            for(int i=0;i<26;i++)
                father[i]=i;
            while(n--){
                scanf("%s",str);
                int len=strlen(str);
                int u=str[0]-'a';
                int v=str[len-1]-'a';
                vis[u]=vis[v]=1;
                int fx=findSet(u);
                int fy=findSet(v);
                if(fx!=fy){
                    father[fy]=fx;
                }
                indeg[v]++;
                outdeg[u]++;
            }
            if(Judge())
                printf("Ordering is possible.\n");
            else
                printf("The door cannot be opened.\n");
        }
        return 0;
    }

    欧拉回路+DFS:

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    #define VM 30
    
    int indeg[VM],outdeg[VM],mat[VM][VM],start;
    bool vis[VM];
    
    void dfs (int u)
    {
        for (int i = 0; i < 26; i ++)
            if (mat[u][i])
            {
                mat[u][i] = 0;
                dfs(i);
            }
    
    }
    bool cmp()
    {
        int i,k,sum1,sum2,sum3;
        sum1 = sum2 = sum3 = 0;
        for (i = 0; i < 26; i ++)
        {
            if (indeg[i] - outdeg[i] == 1)
                sum1 ++;
            if (outdeg[i] - indeg[i] == 1)
            {
                sum2 ++;
                start = i;
            }
            if (indeg[i] == outdeg[i]&&indeg[i]!= 0)
                k = i;
            if (abs(indeg[i] - outdeg[i]) > 1)
                sum3 ++;
        }
    
        if (sum1 > 1||sum2 > 1||sum3 > 0)
            return false;
        if (sum2 == 0)
            start = k;
        return true;
    }
    int main ()
    {
        int T,n;
        bool flag;
        char str[1005];
        scanf ("%d",&T);
        while (T --)
        {
            scanf ("%d",&n);
            memset (indeg,0,sizeof(indeg));
            memset (outdeg,0,sizeof(outdeg));
            memset (mat,0,sizeof(mat));
            memset (vis,false,sizeof(vis));
            while (n --)
            {
                scanf ("%s",str);
                int len = strlen(str);
                int u = str[0]-'a';
                int v = str[len-1]-'a';
                mat[u][v] = 1;
                indeg[v] ++;
                outdeg[u] ++;
            }
            flag = false;
            if (cmp ())
            {
                flag = true;
                dfs(start);
                for (int i = 0; i < 26; i ++)
                    for (int j = 0; j < 26; j ++)
                        if (mat[i][j])
                        {
                            flag = false;
                            break;
                        }
            }
            if (flag)
                printf ("Ordering is possible.\n");
            else
                printf ("The door cannot be opened.\n");
        }
        return 0;
    }
  • 相关阅读:
    一道看似简单的sql需求却难倒各路高手
    MahApps.Metro怎么调用消息窗口
    CodeSmith Generator 7.0.2激活步骤
    8款图表插件推荐
    VS的代码分析工具
    RDLC系列之六 打印纸张的大小(未解决)
    初识python
    应用程序的更新
    Expression<Func<T,TResult>>和Func<T,TResult>
    HTML5 history新特性pushState、replaceState
  • 原文地址:https://www.cnblogs.com/jackge/p/3053257.html
Copyright © 2020-2023  润新知