题意:
给出一些字符串,有这两个字符串,如果第一个字符串的最后一个字母和第二个字符串的第一个字母是一样的,则这两个字符串是可以连接在一起的。
问给出的这些字符串能否串成一个环或者一整个链。
思路:
将头部看做是入度,将尾部看做是出度,如果是一个链的话那么
链的头部那个字母:indegree = outdegree+1;
链的尾部那个字母:indegree+1 = outdegree;
中间出现的字母:indegree = outdegree;
首先用并查集看看给出的这些链能不能连成一个连通分量,如果不是一个连通分量,那就一定不能连成一条链或者一个环。
然后根据欧拉路径(欧拉回路)的入度和出度的性质来判断。
欧拉路径:(百度百科)
代码:
#include <bits/stdc++.h> #include <cstdio> #include <cstring> #include <iostream> #include <vector> #include <algorithm> #include <queue> #include <iomanip> #define MAX 1000000000 #define inf 0x3f3f3f3f #define FRE() freopen("in.txt","r",stdin) using namespace std; typedef long long ll; const int maxn = 1050; int n; int fa[30],vis[30],in[30],out[30]; char str[maxn]; int _find(int x) { return fa[x]==x ? x:fa[x] = _find(fa[x]); } void init() { for(int i=0; i<30; i++) { fa[i] = i; in[i] = out[i] = 0; vis[i] = 0; } } int main() { //FRE(); int kase; scanf("%d",&kase); while(kase--) { init(); scanf("%d",&n); for(int i=0; i<n; i++) { scanf("%s",str); int u = str[0]-'a',v = str[strlen(str)-1]-'a'; in[u]++; out[v]++; vis[u] = vis[v] = 1; u = _find(u); v = _find(v); if(u != v) { fa[u] = v; } } int a=0,b=0,c=0,d=0; for(int i=0; i<26; i++) { if(vis[i] && fa[i]==i) { c++; }//首先得是一个连通分量才能连成一个环或者是一条链 if(vis[i]) { if(in[i]==out[i]) continue; else if(in[i]+1==out[i]) a++;//尾部的字母 else if(in[i]==out[i]+1) b++;//头部的字母 else d++;//中间不符合条件的情况 } } //cout<<a<<" "<<b<<" "<<c<<endl; if(c>1 || d>0) { puts("The door cannot be opened."); } else if((a==0&&b==0) || (a==1&&b==1)) { puts("Ordering is possible."); } else { puts("The door cannot be opened."); } } return 0; }