UVA 10129-Play on Words(欧拉通路)

题意:给N个单词,判断是否单词首尾(前一个单词的尾字符与后一个单词的头字符相同)相连能否形成一条链。

解析:找欧拉通路(欧拉回路或是欧拉链路),但这题事先需要并查集一下,判断是否只属于一个集合,如aa,bb,cc不能形成一条链,但会判断成欧拉回路。

代码如下:

#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<set>
#include<map>
#include<queue>
#include<vector>
#include<iterator>
#include<utility>
#include<sstream>
#include<iostream>
#include<cmath>
#include<stack>
using namespace std;
const int INF=1000000007;
const double eps=0.00000001;
int N,nodenum;
int d[26];
int root(int a)
{
    while(d[a]!=a) a=d[a];
    return a;
}
bool merg(int a,int b)                 //合并
{
    int ra=root(a);
    int rb=root(b);
    if(ra!=rb){ d[ra]=rb; return true; }
    return false;
}
int indeg[26],outdeg[26];     //入度,出度
bool vis[26];
char S[1005];
void input()
{
    nodenum=0;
    cin>>N;
    for(int i=1;i<=N;i++)
    {
        scanf("%s",S);
        int pre=S[0]-'a',last=S[strlen(S)-1]-'a';
        if(!vis[pre]){ vis[pre]=true; nodenum++; }   //标记并节点数加一
        if(!vis[last]){ vis[last]=true; nodenum++; }
        outdeg[pre]++;
        indeg[last]++;
        if(merg(pre,last))  nodenum--;   //减1
    }
}
bool check()                   //判断是否有欧拉通路
{
    int f1=0,f2=0;
    for(int i=0;i<26;i++)
    {
        if(indeg[i]+1==outdeg[i])  f1++;
        else if(indeg[i]==outdeg[i]+1) f2++;
        else if(indeg[i]!=outdeg[i])  return false;
    }
    if((f1==0&&f2==0)||(f1==1&&f2==1))  return truereturn false;
}
int main()
{
    int T;
    cin>>T;
    while(T--)
    {
       for(int i=0;i<26;i++)  d[i]=i;
       memset(vis,false,sizeof(vis));
       memset(indeg,0,sizeof(indeg));
       memset(outdeg,0,sizeof(outdeg));
       input();
       if(nodenum!=1)  { printf("The door cannot be opened.
"); continue; }//如果不等于1代表有多个集合
       if(check())  printf("Ordering is possible.
");
       else  printf("The door cannot be opened.
");
    }
    return 0;
}
原文地址:https://www.cnblogs.com/wust-ouyangli/p/4743288.html