首页 > 代码库 > Play on Words UVA 10129 (有向图的欧拉路)

Play on Words UVA 10129 (有向图的欧拉路)

说说:

这道题的题意很简单,就是给你一些单词,问是否能形成一个句子,使前一个单词的最后一个字母等于后一个单词的第一个字母。本质上来说就是有向图的欧拉路问题,当然存在欧拉回路也是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 (有向图的欧拉路)