算法学习之路|Play On Words(欧拉道路+dfs)

简介: 把单词相接转换成26字母间的有向图,问题就转化成求有向图是否构成欧拉道路。

题目大意:给出n个单词,问能否把这些单词首尾相接(每个单词第一个字母和上一个单词最后一个字母相同)

分析:把单词相接转换成26字母间的有向图,问题就转化成求有向图是否构成欧拉道路。

ac代码:

#include
#include
#include
#include
#define maxn 30
using namespace std;
int vis[maxn],G[maxn][maxn],f[maxn],in[maxn],out[maxn];
void dfs(int x)
{
    vis[x]=true;
    for(int i=0;i<maxn;i++)//向前搜索
    {
        if(G[i][x]&&!vis[i])
            dfs(i);
    }
    for(int i=0;i<maxn;i++)//向后搜索
    {
        if(G[x][i]&&!vis[i])
            dfs(i);
    }
}

int main()
{
    int t,n;
    scanf("%d",&t);
    while(t--){
        memset(G, 0, sizeof(G));
        memset(in, 0, sizeof(in));
        memset(out, 0, sizeof(out));
        memset(vis, 0, sizeof(vis));
        char str[1005];
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%s",str);
            G[str[0]-'a'][str[strlen(str)-1]-'a']++;
            out[str[0]-'a']++;//出度
            in[str[strlen(str)-1]-'a']++;//入度
        }
        bool flag=true;
        int num1=0,num2=0;
        for(int i=0;i<maxn;i++)//判断入度出度是否满足条件
        {
             if(!flag) 
             break; 
            if(in[i]!=out[i])
            {
                 if(in[i]==out[i]+1)
                     num1++; 
                 else if(out[i]==in[i]+1)
                     num2++; 
                 else 
                 {
                     flag=false;
                     break; 
                 } 
            } 
        } 
        if(num1&&num2&&num1+num2>2)
            flag=false;
        if(flag)
        {
            for(int i=0;i<maxn;i++)
                if(out[i])
                {
                    dfs(i);
                    break;
                }
            bool flag2=true;
            for(int i=0;i<maxn;i++)//判断是否连通
            {
                if(in[i]&&!vis[i])
                {
                    flag2=false;
                    break;
                }
                if(out[i]&&!vis[i])//这个if可以去掉,重复了
                {
                    flag2=false;
                    break;
                }
            }
            if(flag2) printf("Ordering is possible.\n");
            else printf("The door cannot be opened.\n");
        }
        else
        {
            printf("The door cannot be opened.\n");
        }
    }
    return 0;
}

此处用的不是并查集而是dfs,因此会出现一个问题,如果只向前搜索可能会导致无环图没有完整遍历,比如从单词链中间某一个单词开始dfs的话,会使得这个单词之间的单词被忽略掉,因为是有向图,从而即使是从一个连通分量中的点(单词),也没有被标记过。

顺便回顾dfs,要注意边界条件。

目录
相关文章
|
11天前
|
存储 算法
数据结构与算法学习二二:图的学习、图的概念、图的深度和广度优先遍历
这篇文章详细介绍了图的概念、表示方式以及深度优先遍历和广度优先遍历的算法实现。
27 1
数据结构与算法学习二二:图的学习、图的概念、图的深度和广度优先遍历
|
8天前
|
缓存 算法 Java
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
这篇文章详细介绍了Java虚拟机(JVM)中的垃圾回收机制,包括垃圾的定义、垃圾回收算法、堆内存的逻辑分区、对象的内存分配和回收过程,以及不同垃圾回收器的工作原理和参数设置。
29 4
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
|
9天前
|
算法
动态规划算法学习三:0-1背包问题
这篇文章是关于0-1背包问题的动态规划算法详解,包括问题描述、解决步骤、最优子结构性质、状态表示和递推方程、算法设计与分析、计算最优值、算法实现以及对算法缺点的思考。
32 2
动态规划算法学习三:0-1背包问题
|
9天前
|
算法
动态规划算法学习四:最大上升子序列问题(LIS:Longest Increasing Subsequence)
这篇文章介绍了动态规划算法中解决最大上升子序列问题(LIS)的方法,包括问题的描述、动态规划的步骤、状态表示、递推方程、计算最优值以及优化方法,如非动态规划的二分法。
37 0
动态规划算法学习四:最大上升子序列问题(LIS:Longest Increasing Subsequence)
|
9天前
|
算法
动态规划算法学习二:最长公共子序列
这篇文章介绍了如何使用动态规划算法解决最长公共子序列(LCS)问题,包括问题描述、最优子结构性质、状态表示、状态递归方程、计算最优值的方法,以及具体的代码实现。
40 0
动态规划算法学习二:最长公共子序列
|
9天前
|
缓存 负载均衡 算法
nginx学习:配置文件详解,负载均衡三种算法学习,上接nginx实操篇
Nginx 是一款高性能的 HTTP 和反向代理服务器,也是一个通用的 TCP/UDP 代理服务器,以及一个邮件代理服务器和通用的 HTTP 缓存服务器。
17 0
nginx学习:配置文件详解,负载均衡三种算法学习,上接nginx实操篇
|
11天前
|
存储 算法 关系型数据库
数据结构与算法学习二一:多路查找树、二叉树与B树、2-3树、B+树、B*树。(本章为了解基本知识即可,不做代码学习)
这篇文章主要介绍了多路查找树的基本概念,包括二叉树的局限性、多叉树的优化、B树及其变体(如2-3树、B+树、B*树)的特点和应用,旨在帮助读者理解这些数据结构在文件系统和数据库系统中的重要性和效率。
13 0
数据结构与算法学习二一:多路查找树、二叉树与B树、2-3树、B+树、B*树。(本章为了解基本知识即可,不做代码学习)
|
11天前
|
存储 算法 数据管理
数据结构与算法学习二零:二叉排序树(BST)、平衡二叉树(AVL)
这篇文章通过需求分析、代码实现和测试验证,详细介绍了二叉排序树的创建、遍历和删除操作,以及二叉平衡树(AVL)的自平衡特性和单旋转操作,旨在提高树结构在数据管理中的效率和性能。
17 0
数据结构与算法学习二零:二叉排序树(BST)、平衡二叉树(AVL)
|
9天前
|
存储 算法
动态规划算法学习一:DP的重要知识点、矩阵连乘算法
这篇文章是关于动态规划算法中矩阵连乘问题的详解,包括问题描述、最优子结构、重叠子问题、递归方法、备忘录方法和动态规划算法设计的步骤。
42 0