说说:
这道题的题意很简单,就是给你一些单词,问是否能形成一个句子,使前一个单词的最后一个字母等于后一个单词的第一个字母。本质上来说就是有向图的欧拉路问题,当然存在欧拉回路也是OK的。一开始的时候,我以为存在欧拉路只需判断两种情况:一,是存在欧拉回路,即每个节点的入度等于出度。二,存在欧拉路,有且仅有一个节点的入度比出度大一,一个节点的出度比入度大一。只要满足任意其中一种情况即可。事实上不是这样的,其实还需要判断该图是否连通。这自然而然就想到了并查集的思想。当出现两个节点的时候,将其中的一个节点指向另一个节点的根,最后判断所有节点的根是否相同。若相同,则是连通图。(其实可以证明,第二种情况肯定是连通的)
源代码:
#include <stdio.h> #include <string.h> #define MAX 1000+5 int fa[26]; int find(int i){//并查集 if(fa[i]!=i) return fa[i]=find(fa[i]); else return fa[i]; } int main(){ int T,M,i,len,Fa; char word[MAX]; int in[26];//入度 int out[26];//出度 int vis[26]; int YES,inone,outone; //freopen("data","r",stdin); scanf("%d",&T); while(T--){ YES=1; inone=outone=0; memset(in,0,sizeof(in)); memset(out,0,sizeof(out)); memset(vis,0,sizeof(vis)); for(i=0;i<26;i++) fa[i]=i; scanf("%d",&M); for(i=0;i<M;i++){ scanf("%s",word); len=strlen(word); out[word[0]-'a']++; in[word[len-1]-'a']++; vis[word[0]-'a']=vis[word[len-1]-'a']=1; fa[word[0]-'a']=Fa=find(word[len-1]-'a'); } for(i=0;i<26;i++) if(vis[i]&&find(i)!=Fa) YES=0; if(YES) for(i=0;i<26;i++) if(in[i]!=out[i]){ if(in[i]==out[i]+1) inone++;//入度比出度大一的节点数 else if(out[i]==in[i]+1) outone++;//出度比入度大一的节点数 else{ YES=0; break; } } if(YES&&inone==outone&&(inone==1||inone==0)) printf("Ordering is possible.\n"); else printf("The door cannot be opened.\n"); } return 0; }
时间: 2024-10-15 20:53:23