Play on Words(欧拉通路)
题目大意
给多个单词 让你判断单词能否接龙(后一个单词的第一个字母 是 前一个单词的最后一个字母)
算法
欧拉回路/通路
欧拉回路意思是 如果一个连通图中 每一个点的出度等于入度的话 那么可以由其中任意一个点开始 走出一条不往返的路劲(一笔画) 且回到起点
欧拉通路就是在欧拉回路很类似(也是一笔画) 不同的是不能回到起点 因此起点的出度大于入度 终点的入度大于出度
本题将每个string的front 和 back看成节点 中间的其他字符为路 若所有string组成的图 存在欧拉通路/回路 则说明满足题意
思路是先判断是否连通 不连通直接false 连通的话再判断是否存在欧拉通路/回路
利用set存节点 并查集确定是否连通
代码
#include<cstdio>
#include<set>
#include<vector>
#include<algorithm>
#include<string>
#include<cstring>
#include<iostream>
using namespace std;
int f[27], in[27], out[27];
set<char> letters;
int Find(int x)
{
if(x == f[x])
return x;
int temp = Find(f[x]);
f[x] = temp;
return temp;
}
bool judge(int in[], int out[], int n)
{
int num = 0;
for(int i = 0;i < 26;i++)
{
if(f[i] == i)
num++;
}
if((26 - n + 1) != num)
return false;
int num1 = 0, num2 = 0;//1-in 2-out
for(int i = 0;i < 26;i++)
{
int j = in[i] - out[i];
if(abs(j > 1))
return false;
else if(j == 1)
num1++;
else if(j == -1)
num2++;
}
return (num1 == 1 && num2 == 1) || (num1 == 0 && num2 == 0);
}
void ini()
{
memset(in, 0, sizeof(in));
memset(out, 0, sizeof(out));
letters.clear();
for(int i = 0;i <= 26;i++)
f[i] = i;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
ini();
int n;
scanf("%d",&n);
string s;
for(int i = 0;i < n;i++)
{
cin >> s;
++in[s.front() - 'a'];
++out[s.back() - 'a'];
letters.insert(s.back());
letters.insert(s.front());
int ua = Find(s.front()-'a'),ub = Find(s.back()-'a');
if( ua != ub )
f[ua] = ub;
}
if(judge(in, out,letters.size()))
printf("Ordering is possible.\n");
else
printf("The door cannot be opened.\n");
}
return 0;
}

浙公网安备 33010602011771号