说说:
这道题的题意很简单,就是给你一些单词,问是否能形成一个句子,使前一个单词的最后一个字母等于后一个单词的第一个字母。本质上来说就是有向图的欧拉路问题,当然存在欧拉回路也是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;
}Play on Words UVA 10129 (有向图的欧拉路)
原文地址:http://blog.csdn.net/u011915301/article/details/39558329