UVA 10129 Play on Words

题意:

  有一些秘密的门包含着非常有趣的单词迷题, 考古学家队伍必须解决它们才能够打开大门。 因为没有其他方法能偶打开这些门, 所以解决那些迷题对我们非常重要。在每个门上有很多个有磁力的盘子,盘子上面写着单词。 必须重新移动放置这些盘子,让它们形成一个队列:队列中,除了第一个单词,每个单词的开头和上一个单词的结尾字母

分析:

  对于有向图, 则必须其中一个点的出度恰好比入度大1, 另一个的入度比出度大。如果奇点数不存在的话, 则可以从任意点出发,最终一定会回到该点(成为欧拉回路)。题目给的单词量比较大,但是有用的只有首和尾的字母,所以只需要存首尾字母就可以了。 接下来dfs搜索。

代码;

  

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
#define MAXN 100
int vis[MAXN],G[MAXN][MAXN],N,T,f[MAXN],rank[MAXN],in[MAXN],out[MAXN];
void dfs(int u)
{
vis[u]=1;
//cout<<u<<endl;
for(int i=0;i<MAXN;i++)
{
if(G[u][i]&&!vis[i])
dfs(i);
}
}
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d",&N);
memset(G,0,sizeof(G));
memset(in,0,sizeof(in));
memset(out,0,sizeof(out));
char str[1005];
int i;
for(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(i=0;i<MAXN;i++)
{
if(!flag)
break;
if(in[i]!=out[i])
{
if(in[i]==out[i]+1)
++num1;
else if(in[i]+1==out[i])
++num2;
else
{
flag=false;
break;
}
}
}
if(num1&&num2&&num1+num2>2)
flag=false;
if(flag)
{
memset(vis,0,sizeof(vis));
for(i=0;i<MAXN;i++)
{
if(out[i])
{
dfs(i);
break;
}
}
bool flag2=true;
for(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. ");
else
printf("The door cannot be opened. ");
}
else
printf("The door cannot be opened. ");
}
}
原文地址:https://www.cnblogs.com/137033036-wjl/p/4891077.html