Play on Words UVA - 10129

题目:

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.

题目大意翻译:

有一些秘密的门包含着非常有趣的单词迷题, 考古学家队伍必须解决它们才能够打开大门。 因为没有其他方法能偶打开这些门, 所以解决那些迷题对我们非常重要。

在每个门上有很多个有磁力的盘子,盘子上面写着单词。 必须重新移动放置这些盘子,让它们形成一个队列:队列中,除了第一个单词,每个单词的开头和上一个单词的结尾字母

一样。例如, motorola的后面可以接上acm。

你的任务是写一个程序, 读入一系列单词,然后计算确定它们是否有可能被排成这样的队列。

样例输入:

3
2
acm
ibm
3
acm
malform
mouse
2
ok
ok

样例输出:

The door cannot be opened.
Ordering is possible.
The door cannot be opened.开始用dfs写的,结果因为数据太大,时间超限,然后再网上搜了下才知道是用欧拉回路加dfs做的这是我的dfs代码
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
char mapn[100010][1010];
int flag,n,vis[100010];
void dfs(char c,int a)
{
    if( a == n)
    {
        flag = 1;
        return;
    }
    for(int i=0;i<n;i++)
    {
        if(mapn[i][0] == c && !vis[i])
        {
            vis[i] = 1;
            dfs(mapn[i][strlen(mapn[i])-1],++a);
            vis[i] = 0;
        }
    }
    return;
}
int main()
{
    int t;
    cin >> t;
    while(t--)
    {
        flag = 0;
        memset(vis,0,sizeof(vis));
        memset(mapn,0,sizeof(mapn));
        cin >> n;
        for(int i=0;i<n;i++)
            cin >> mapn[i];
        for(int i=0;i<n;i++)
        {
            vis[i] = 1;
            dfs(mapn[i][strlen(mapn[i])-1],1);
            vis[i] = 0;
        }
        if(flag)
            cout << "Ordering is possible." << endl;
        else cout << "The door cannot be opened." << endl;
    }
    return 0;
}

下面这个是用欧拉回路加dfs做的

#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#define MAXN 100
using namespace std;
int vis[MAXN],G[MAXN][MAXN],N, T, in[MAXN],out[MAXN];
void dfs(int u)//只用dfs会时间超限
{
    vis[u] = true;
    for(int i=0; i<MAXN; ++i)
    {
        if(G[u][i] && !vis[i])
            dfs(i);
    }
}
int main()
{
    scanf("%d",&T);
    while(T--)
    {
        memset(G, 0, sizeof(G));
        memset(in, 0, sizeof(in));
        memset(out, 0, sizeof(out));
        char str[1005];
        scanf("%d",&N);
        for(int i=0; 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;
            /*对于有向图, 则必须其中一个点的出度恰好比入度大1,
             另一个的入度比出度大。
                如果奇点数不存在的话,
                则可以从任意点出发,最终一定会回到该点(成为欧拉回路)。*/
            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)
        {
            memset(vis, 0, sizeof(vis));
            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])
                {
                    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;
}
时间: 2024-08-08 13:56:04

Play on Words UVA - 10129的相关文章

Play on Words UVA - 10129 欧拉路径

关于欧拉回路和欧拉路径 定义:欧拉回路:每条边恰好只走一次,并能回到出发点的路径欧拉路径:经过每一条边一次,但是不要求回到起始点 ①首先看欧拉回路存在性的判定: 一.无向图每个顶点的度数都是偶数,则存在欧拉回路. 二.有向图(所有边都是单向的)每个节顶点的入度都等于出度,则存在欧拉回路. ②.欧拉路径存在性的判定 一.无向图一个无向图存在欧拉路径,当且仅当   该图所有顶点的度数为偶数   或者  除了两个度数为奇数外其余的全是偶数. 二.有向图一个有向图存在欧拉路径,当且仅当  该图所有顶点的

Play on Words UVA - 10129 (有向图欧拉路径)

Play on Words UVA - 10129 题意:n个单词,问能否收尾相连形成一条链. 把单词首尾字母看做点,单词内部连一条边,问是否存在欧拉路径. 用并查集,当且仅当只有一个点的出度比入度大1一个点的入度比出度大1其它点出度和入度相等时存在欧拉路径. 1 #include<cstdio> 2 #include<cstring> 3 #include<set> 4 #include<iostream> 5 #include<cctype>

uva 10129 Play on Words(欧拉路)

uva 10129 Play on Words Description Play on Words 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 impo

UVa 10129 单词

题意:给定一些单词,单词的尾字母和另一单词的首字母相同,则可以串联,问是否可以将所有的单词串联.单词可重复出现,但每个单词只能用一次:即某单词重复几次,则可用几次. 思路:欧拉道路的应用.欧拉道路,即"一笔画",从图中一结点出发走一条道路,每条边恰好经过一次. 首先要判断图是连通的. 对于无向图,最多只有两个奇点(度数为奇数).且从一奇点出发,到另一奇点终止:若无奇点,则可从任意点出发,最终定会回到该点(欧拉回路). 对于有向图,最多只能有两个点的入度不等于出度,且必须其中一点的出度恰

Uva(10129)+Uva(10054)

这两道题都是和欧拉图的判定有关,一个是有向图,一个是无向图的欧拉图的判定还有一个是有向图= = 先看10129...我们把单词的首字母看做是入度,最后一个字符看做是初度,那么这道题就变成图中是否存在欧拉回路.判断有向图的条件是该图是连通图和最多最有两个点的出度不等于入度,其实那两个点就是起点和终点,而且必须是其中一个点的入度比出度恰好大1(作为终点),另一个点的出度比它的入度恰好大1(作为起点) 连通图的话我们用并查集来判断,如果该图是连通图的话,那么他们共用祖先= = #include<std

UVA 10129 Play on Words(欧拉道路)

题意:给你n个字符串,问你是否可以出现一条链,保证链中每个字符串的第一个元素与上一个字符串的最后一个元素相同,注意可能重复出现同一个字符串 题解:以每一个字符串第一个元素指向最后一个元素形成一个有向图,判断这个有向图是否可以形成欧拉路就好 注意可能有重边与自环,因此求欧拉路时判断的是是否使用完了所有的边,求起点时注意出度与入度的计算 欧拉道路是从一个点一笔画完整张图(欧拉回路保证回到起点),注意除了起点与终点以外所有的点出度入度相等 起点出度大入度1,终点相反(所有的点出入度相等也可以),根据这

UVA - 10129 Play on Words(欧拉回路+并查集)

2.解题思路:本题利用欧拉回路存在条件解决.可以将所有的单词看做边,26个字母看做端点,那么本题其实就是问是否存在一条路径,可以到达所有出现过的字符端点.由于本题还要求了两个单词拼在一起的条件是前一个单词的右端点和本单词的左端点一样.所以这是一个有向图.根据结论:有向图的底图(忽略边的方向后的图)必须连通:有向图中最多只能有两个端点的入度不等于出度,且必须是其中一点的入度比出度小1,另一点的入度比出度大1.因此先判断端点是否都连通,再判断每个端点的度数是否满足结论即可. 那么,如何判断连通性呢?

UVa 10129 Play On Words【欧拉道路 并查集 】

题意:给出n个单词,问这n个单词能否首尾接龙,即能否构成欧拉道路 按照紫书上的思路:用并查集来做,取每一个单词的第一个字母,和最后一个字母进行并查集的操作 但这道题目是欧拉道路(下面摘自http://blog.csdn.net/hcbbt/article/details/9316301) 关于欧拉道路(from Titanium大神): 判断有向图是否有欧拉路 1.判断有向图的基图(即有向图转化为无向图)连通性,用简单的DFS即可.如果图都不连通,一定不存在欧拉路 2.在条件1的基础上   对于

uva 10129 play on words——yhx

把每个字母看成一个结点,每个单词看成一条从第一个字母到最后一个字母的有向边.把这些单词首尾相接相当于寻找欧拉路径(一笔画). 则其需满足两个条件:1.忽略边的方向后,原图联通.2.一个点的入度比出度大1,另一个点入度比出度小1,其他点入度和出度相等. 1 #include<cstdio> 2 #include<cstring> 3 using namespace std; 4 int in[30],out[30],n; 5 bool b[30],map[30][30]; 6 voi