题目描述
给出n个单词,问能否完成所有单词的单词接龙。
思路
如果以单词为节点,条件为边建图,我们就要在图上求是否存在一条哈密尔顿道路,这显然难以实现。我们考虑以单词为边,以字母为节点,那么题目就相当于在图上求一条欧拉道路,但我们并不知道图是否是一张连通图,非连通图显然无法找到一条欧拉路径。所以我们还要再尝试找一遍欧拉路径来判断是否连通。而找欧拉路径容易造成栈溢出,所以我们可以递归改循环。当然用并查集判连通性也可以。
#include <bits/stdc++.h> using namespace std; const int N=30,M=1e5+10; int nxt[M],to[M],tot,head[N]; void add_edge(int x,int y) { nxt[++tot]=head[x]; head[x]=tot; to[tot]=y; } int read() { int res=0,w=1; char ch=getchar(); while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)w=-1;ch=getchar();} while(ch>=‘0‘&&ch<=‘9‘){res=(res<<3)+(res<<1)+ch-‘0‘;ch=getchar();} return res*w; } int st[M],top; bool vis[M]; void euler(int s) { st[++top]=s; while(top>=1) { int x=st[top],i=head[x]; while(i&&vis[i])i=nxt[i]; if(i) { st[++top]=to[i]; head[x]=nxt[i]; vis[i]=1; } else --top; } } char s[1100]; int in[30],out[30]; int main() { int t=read(); while(t--) { memset(head,0,sizeof(head)); memset(vis,0,sizeof(vis)); memset(in,0,sizeof(in)); memset(out,0,sizeof(out)); top=0;tot=0; int n=read(); for(int i=1;i<=n;i++) { scanf(" %s",s); int x=s[0]-‘a‘+1,y=s[strlen(s)-1]-‘a‘+1; // cout<<x<<‘ ‘<<y<<endl; in[y]++;out[x]++; add_edge(x,y); } bool f=1; int cnt1=0,cnt2=0,st=1; for(int i=1;i<=26;i++) { if(in[i]-out[i]==1)cnt1++; else if(out[i]-in[i]==1)cnt2++,st=i; else if(out[i]!=in[i])f=0; if(cnt1>1||cnt2>1)f=0; } euler(st); for(int i=1;i<=n;i++) if(!vis[i]){f=0;break ;} if(f)printf("Ordering is possible.\n"); else printf("The door cannot be opened.\n"); } }
代码
原文地址:https://www.cnblogs.com/fangbozhen/p/11748550.html
时间: 2024-10-07 08:46:29