在进行题目分析前,先澄清一些概念,一些图论中很重要的概念然后给出思路:
节点度
英文:Node Degree
图论中:
节点度是指和该节点相关联的边的条数。
特别地,对于有向图,
节点的入度 是指进入该节点的边的条数;
节点的出度是指从该节点出发的边的条数。
对于无向图:
思路(很重要):
将一个单词的首字母和尾字母看做结点,该单词看做是一条边。
则依照题意,即判断所建图是不是存在欧拉回路或是欧拉通路,根据有向图的欧拉回路充要条件
1、如果有向图存在欧拉回路,则其基图是连通图(基图是将有向图变为无向图),每个结点的入度等于出度。
2、如果有向图存在欧拉通路,则其基图是连通图,只有一个结点的入度比出度大1,只有一个结点的出度比入度
大1,其余点入度皆等于出度。
有了以上知识,很简单就可以AC这个题目,代码如下:
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <cstring>
#include <vector>
#define M 26
using namespace std;
int n, in[M], out[M];
bool v[M];
vector<int> e[M];
void dfs( int s)
{
v[s] = true;
for ( int i = 0; i < e[s].size(); i++ )
if ( !v[e[s][i]]) dfs(e[s][i]);
}
bool tell( int s )
{
memset(v,0,sizeof(v));
dfs(s);
for ( int i = 0; i < 26; i++ )
if ( !v[i] && e[i].size()!=0 )
return false;
return true;
}
int main()
{
int ca, i, j, k, a, b;
char s[1002];
int flag;
freopen( "ex.in", "r", stdin );
cin >> ca;
while ( ca-- )
{
cin >> n;
for ( i = 0; i < 26; i++ )
e[i].clear();
memset(in,0,sizeof(in));
memset(out,0,sizeof(out));
for ( i = 0; i < n; i++ )
{
scanf("%s", s);
a = s[0]-'a'; b = s[strlen(s)-1]-'a';
in[b]++; out[a]++;
e[a].push_back(b);
e[b].push_back(a);
}
if ( !tell(a) )
{
printf( "The door cannot be opened.\n");
continue;
}
flag = 0;
for ( i = 0; i < 26; i++ )
if ( in[i] != out[i] )
{
if ( abs(in[i]-out[i])==1 ) flag++; else break;
if ( flag > 2 ) break;
}
if ( i < 26 ) printf( "The door cannot be opened.\n");
else printf( "Ordering is possible.\n");
}
}