`

poj 2337 Catenyms(并查集+dfs+欧拉回路)

阅读更多

Catenyms

Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 131072/65536K (Java/Other)
Total Submission(s) : 6   Accepted Submission(s) : 5
Problem Description
A catenym is a pair of words separated by a period such that the last letter of the first word is the same as the last letter of the second. For example, the following are catenyms:
dog.gopher

gopher.rat

rat.tiger

aloha.aloha

arachnid.dog

A compound catenym is a sequence of three or more words separated by periods such that each adjacent pair of words forms a catenym. For example,

aloha.aloha.arachnid.dog.gopher.rat.tiger

Given a dictionary of lower case words, you are to find a compound catenym that contains each of the words exactly once.

 

Input
The first line of standard input contains t, the number of test cases. Each test case begins with 3 <= n <= 1000 - the number of words in the dictionary. n distinct dictionary words follow; each word is a string of between 1 and 20 lowercase letters on a line by itself.

 

Output
For each test case, output a line giving the lexicographically least compound catenym that contains each dictionary word exactly once. Output "***" if there is no solution.

 

Sample Input
2 6 aloha arachnid dog gopher rat tiger 3 oak maple elm
 

 

Sample Output
aloha.arachnid.dog.gopher.rat.tiger ***
 
         题目大意:输入n个单词,每个单词都形成一条从该单词首字母到尾字母的边,单词尾字母要与下一个单词首字母相同,若可以组成这样的路,即可以组成这样一条连着的单词串,输出路径(单词串),若有多条,则要按字典顺序输出,找不到路则输出***。
         此题搞了很长的时间啊,主要是建边那一部分,看了很久,不能用邻接矩阵,后来就用了链表,还有输出路径这个难搞啊,后来参考了一下别人的代码,发现那个dfs路径竟然如此巧妙!实在很巧妙!
代码:
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <cstring>
#include <string>
#include <algorithm>
#include <math.h>
using namespace std;

bool app[30];
char res[1005][26];
int in[30], out[30], deg[30], father[30], adj[30];
int n, ant, odd, begin, end;

struct edge
{
    bool vis;
    char sh[25];
    int y, next;
}a[1005];

bool cmp(edge a, edge b)
{
    return strcmp(a.sh, b.sh) > 0;
}

void init()
{
    int i;
    ant = odd = 0;
    memset(app, false, sizeof(app));
    memset(in, 0, sizeof(in));
    memset(out, 0, sizeof(out));
    memset(deg, 0, sizeof(deg));
    memset(adj, -1, sizeof(adj));
    for(i = 0; i < 1005; i++) a[i].vis = false;
    for(i = 0; i < 26; i++) father[i] = i;
}

int find(int x)
{
    if(x != father[x])
    {
        father[x] = find(father[x]);
    }
    return father[x];
}

void Union(int x, int y)
{
    father[x] = y;
}

int judge()     //判断是否满足欧拉。0不满足,1欧拉回路,2欧拉路
{
    int i, k;
    for(i = 0; i < 26; i++)     //判断有向图欧拉
    {
        if(!app[i]) continue;
        deg[i] = in[i] - out[i];
        if(abs(deg[i]) > 1) return 0;
        if(deg[i] > 0) begin = i;   //起点
        if(deg[i] < 0) end = i;     //终点
        if(deg[i]%2) odd++;
        if(odd > 2) return 0;
    }
    for(i = 0; i < 26; i++) if(app[i]) break;
    k = find(i);
    for(i = k+1; i < 26; i++)   //判断连通性
    {
        if(!app[i]) continue;
        if(k != find(i)) return 0;
    }
    if(odd == 0)    //有欧拉回路
    {
        for(i = 0; i < 26; i++)
            if(app[i]) break;
        begin = i;
        return 1;
    }
    return 2;
}

void dfs(int x, int id) //深搜寻找欧拉路径,很巧妙!!!
{
    int i;
	for(i = adj[x]; i != -1; i = a[i].next)
	{
		if(!a[i].vis)
		{
			a[i].vis = true;
			dfs(a[i].y, i);
		}
	}
	if(id != -1) strcpy(res[ant++], a[id].sh);  //最先进去的肯定是终点
}

int main()
{
    int i, x, y, fx, fy, t, len, tar;
    scanf("%d", &t);
    while(t--)
    {
        init();
        scanf("%d", &n);
        for(i = 0; i < n; i++)
        {
            scanf("%s", a[i].sh);
        }
        //题目要求是字典顺序,但是我是用前插链表,这时的顺序恰好会相反
        sort(a, a+n, cmp);  //所以排序时从大到小,这样刚刚会是字典顺序
        for(i = 0; i < n; i++)
        {
            len = strlen(a[i].sh);
            x = a[i].sh[0] - 'a';
            y = a[i].sh[len-1] - 'a';
            in[x]++;
            out[y]++;
            app[x] = true;
            app[y] = true;
            /// *****建边*****
            a[i].y = y;
            a[i].next = adj[x];
            adj[x] = i;
            /// ***************
            fx = find(x);
            fy = find(y);
            if(fx != fy) Union(fx, fy);
        }
        tar = judge();
        if(tar == 0)
        {
            printf("***\n");
            continue;
        }
        dfs(begin, -1);
        printf("%s", res[ant-1]);
        for(i = ant-2; i >= 0; i--)
        {
            printf(".%s", res[i]);
        }
        printf("\n");
    }

    return 0;
}
 
0
1
分享到:
评论

相关推荐

    POJ-2870 Light Up + DFS(1级DFS+1级DFS) + Python - 思维导图

    题目"POJ-2870 Light Up"是一个经典的图论问题,主要涉及深度优先搜索(DFS)算法的运用。该问题要求点亮一个矩形区域内的所有障碍物,每个障碍物需要特定数量的灯光才能被照亮,且相邻的障碍物之间不能有空格。题目...

    POJ 1988 简单并查集,

    根据给定的信息,本文将详细解释“POJ 1988 简单并查集”中的核心知识点,包括并查集的基本概念、代码实现以及在本题中的具体应用。 ### 并查集基本概念 并查集是一种用于处理一些不交集的合并及查询问题的数据...

    POJ1691-Painting A Board 【拓扑+DFS】

    【标题】"POJ1691-Painting A Board 【拓扑+DFS】"是一个源自北京大学在线编程平台POJ的编程题目,它主要涉及到图论中的拓扑排序和深度优先搜索(DFS)算法。该题目的核心是解决一个与涂色相关的实际问题,通过运用...

    poj2492并查集应用的扩展

    poj2492 A Bug's Life并查集应用的扩展,希望可以给大家带来用处

    POJ3009-Curling 2.0【DFS+Vector+回溯+剪枝】

    总的来说,解答POJ3009-Curling 2.0问题需要对DFS、向量、回溯和剪枝有深入的理解,并能灵活运用到具体问题中。通过对这些技术的熟练掌握,不仅可以解决这道题目,还能够为其他类似问题提供有效的解决方案。

    POJ3733-Changing Digits【DFS+强剪枝】

    【标题】"POJ3733-Changing Digits【DFS+强剪枝】"是一个来自北京大学在线评测系统POJ的编程题目,该题目主要涉及深度优先搜索(DFS)算法和强剪枝策略。在算法竞赛和编程挑战中,这类问题通常要求参赛者通过编写...

    POJ3373-Changing Digits【DFS+强剪枝】

    标题“POJ3373-Changing Digits【DFS+强剪枝】”涉及的是一个编程竞赛中的问题,这个问题在北大POJ(北京大学在线评测系统)平台上被提出。"Changing Digits"是一个算法挑战,而解决方案是通过深度优先搜索(DFS)...

    【POJ1330】最近公共祖先(LCA):并查集+深搜 - cxllyg的专栏 - 博客频道 - CSDN.NET1

    对于没有父节点指针的普通二叉树,解决LCA的方法通常涉及到深度优先搜索(DFS)。我们可以从根节点开始,找到给定节点的路径,并存储在向量中。例如,假设我们有以下二叉树: ``` 10 / \ 6 14 / \ / \ 4 8 12 16 ...

    欧拉回路题集

    - **题目描述**:构建特定类型的图——德布鲁因图,并找出其欧拉回路。 - **解题思路**:构建德布鲁因图后,判断其是否存在欧拉回路。 - **数据结构**:邻接表。 5. **【HDU】1956 Sightseeing tour 混合欧拉** ...

    数据结构--并查集(Union-Find Sets)

    此外,它也是算法竞赛中的常见题目类型,例如POJ等在线编程平台上的题目就经常涉及并查集的使用。 综上所述,并查集是一种非常实用的数据结构,它在处理集合的连接与查找问题时具有高效性和灵活性,对于理解和掌握...

    POJ1014-Dividing【DFS】【多重背包+二进制优化】

    在给出的文件列表中,“POJ1014-Dividing【多重背包+二进制优化】.cpp”和“POJ1014-Dividing【DFS】.cpp”很可能是两份不同的C++代码实现,分别展示了如何结合多重背包和二进制优化以及如何利用DFS来解决问题。...

    并查集问题

    1. poj2524.cpp:这是一个POJ(Problem Setter's Online Judge)的编程题目,通常涉及到特定的算法问题,可能需要利用并查集解决连通性或路径查找问题。 2. hdoj1233最小生成树,克鲁斯卡尔.cpp:最小生成树是图论...

    ACM常用算法及其相应的练习题.docx

    * 简单并查集的应用 * 哈希表和二分查找等高效查找法 + poj3349, poj3274, poj2151, poj1840, poj2002, poj2503 * 哈夫曼树:poj3253 * 堆 * Trie树:静态建树、动态建树 + poj2513 四、简单搜索 * 深度优先搜索...

    西北工业大学POJ试题C++答案代码+课程设计

    "西北工业大学POJ试题C++答案代码+课程设计"这一标题表明了资源的主要内容,涉及两个核心部分:一是西北工业大学的编程竞赛(POJ,Problem Oriented Judge System)的C++解题代码,二是与这些题目相关的课程设计。...

    1089_bingchaji.rar_1089_bingchaji.rar _并查集

    在给定的标题“1089_bingchaji.rar_1089_bingchaji.rar _并查集”和描述“POJ1089 并查集可以解决 并查集加路径压缩”中,我们可以看到这是一个关于使用并查集解决特定问题的案例,可能来自于编程竞赛或练习。...

    POJ1020-Anniversary Cake【有技巧的DFS】

    【标题】"POJ1020-Anniversary Cake【有技巧的DFS】"是一个源自北京大学在线编程平台POJ的编程题目,它涉及到深度优先搜索(DFS)算法的应用。这道题目要求参赛者通过编程解决一个有趣的问题,即在特定条件下如何...

    并查集C++实现

    这份代码用C++实现了经典算法并查集,来源于poj题目1182

    POJ1207-The 3n + 1 problem

    《POJ1207-The 3n + 1 problem》是北京大学在线编程平台POJ上的一道经典算法题目,其主要涉及的知识点是数论和动态规划。本题目的核心是解决著名的“Collatz Conjecture”问题,也被称为“3n+1猜想”。 3n+1猜想是...

    并查集(Union Find set)基础

    并查集基础 acm 算法 poj oi 并查集基础.ppt

    POJ1011-Sticks

    一种常见的方法是使用深度优先搜索(DFS)或广度优先搜索(BFS)来构建线段之间的连接,并通过并查集(Disjoint Set)数据结构来判断是否存在不相交的集合。 1. **数据结构**:首先,我们需要用数组或者链表存储...

Global site tag (gtag.js) - Google Analytics