zoukankan      html  css  js  c++  java
  • hdu 1116 Play on Words(欧拉通路)

    题意:给出给出n个单词,要求判断这些单词能否接龙,规则像成语接龙一样,就是当前单词的尾字母为下一个单词的首字母。

    思路:看着像是欧拉通路相关的题目,但是重点就在于怎么抽象出来。

    刚开始想了半天没想明白,老想着一个单词作为一个顶点去了,就是没转过来。

    看了篇解题报告(http://blog.csdn.net/niushuai666/article/details/6917777) 后想过来了,

    应该把单词的首尾字母看成顶点,而这个单词相当于连接顶点的有向边。然后这样想的话,这个图最多就有26个顶点(因为只有26个小写字母,题目要求单词为小写字母),接下来就是怎么判断这个途中是否存在欧拉通路了(即判断是否为半欧拉图或欧拉图)。

    关于欧拉图的相关知识,详见:

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    
    int in[26],out[26];//入度,出度
    int differ[10];//入度不同的顶点
    bool exist[26];//记录字母是否存在
    int set[26];//父亲节点
    int root;//根的数目
    
    int set_find(int d){  
        if(set[d]<0)
            return d;  
        return set[d]=set_find(set[d]);  
    }  
    void join(int x,int y){  //采用路径压缩的并查集,判断是否连通
        x=set_find(x);  
        y=set_find(y);
        if(x!=y) set[x]=y;  
        return;
    }
    
    int main(){
        int t;//测试个数
        int n;//单词个数
        int i;//
        int number;//入度不同的顶点的个数
        char word[1100];//存放单词
        int a,b;
        scanf("%d",&t);
        while(t--){
            memset(in,0,sizeof(in));
            memset(out,0,sizeof(out));
            memset(set,-1,sizeof(set));
            memset(exist,0,sizeof(exist));
            number=0;
            root=0;
            scanf("%d",&n);
            while(n--){
                scanf("%s",word);
                a=word[0]-'a';
                b=word[strlen(word)-1]-'a';
                exist[a]=exist[b]=true;
                out[a]++;
                in[b]++;
                join(b,a);
            }
            for(i=0;i<26;i++){
                if(exist[i]&&set[i]<0)
                    root++;
            }
            if(root>1)//图不连通
                printf("The door cannot be opened.
    ");
            else{
                for(i=0;i<26;i++){
                    if(in[i]!=out[i])
                        differ[number++]=i;
                }
                if(number==0) //所有顶点入度等于出度,为欧拉图
                    printf("Ordering is possible.
    ");
                else if( number==2 && (  //注意&&、||的优先级,此处要加括号
                    (in[differ[0]]-out[differ[0]]==1 && out[differ[1]]-in[differ[1]]==1)||
                    (out[differ[0]]-in[differ[0]]==1 && in[differ[1]]-out[differ[1]]==1) )
                    )//满足半欧拉图条件,为半欧拉图
                    printf("Ordering is possible.
    ");
                else printf("The door cannot be opened.
    ");//不是欧拉图,也不是半欧拉图
            }
        }
        return 0;
    }








  • 相关阅读:
    java.util.Date和java.sql.Date的区别及应用
    powderdesinger显示中英文表名
    Axure实现提示文本单击显示后自动消失的效果
    如何把Java的double类型变量保留两位小数
    MyBatis查询,返回值Map或List<Map>
    Spring Security整合JWT,实现单点登录,So Easy~!
    win10+mysql8.0安装
    Intellij IDEA导入JAVA项目并启动(哈哈哈,天天都有人问)
    色彩设计基础知识整理
    前端开发者必备的Nginx知识
  • 原文地址:https://www.cnblogs.com/gongpixin/p/4477373.html
Copyright © 2011-2022 走看看