poj 1386 Play on Words (欧拉路)

poj 1386

题意:n个单词,问能否形成一个串(单词接龙,收尾相连,当且仅当前一个单词的末尾字母和后一个单词的首字母相同)

思路:欧拉路。

关于欧拉路:

(1)**有向图G为欧拉图(存在欧拉回路),当且仅当G的基图连通(弱联通,),且所有顶点的入度等于出度。**

(2)有向图G为半欧拉图(存在欧拉路),当且仅当G的基图连通(弱联通),且存在顶点u的入度比出度大1、v的入度比出度小1,其它所有顶点的入度等于出度。

(3) 无向图存在欧拉回路:  图连通,所有点都是偶数度,

(4)无向图存在欧拉路:图联通,只有两个点的度数为奇数。

有向图判断联通性判断的弱联通,因此可以用并查集实现。

具体办法是,判断根的个数,个数为大于1表示不联通。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <cmath>
#include <cstdlib>
#include <ctime>
#define fst first
#define sec second
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define ms(a,x) memset(a,x,sizeof(a))
typedef long long LL;
#define pi pair < int ,int >
#define MP make_pair
using namespace std;
const double eps = 1E-8;
const int dx4[4]={1,0,0,-1};
const int dy4[4]={0,-1,1,0};
const int inf = 0x3f3f3f3f;
const int N=26;
int in[N];
int out[N];
int f[N];
int root ( int x)
{
    if (x!=f[x]) f[x] = root(f[x]);
    return f[x];
}
void merge( int x,int y)
{
    int rx = root(x);
    int ry = root(y);
    if (rx!=ry)
	f[rx] = ry;
}
void init()
{
    for ( int i = 0 ; i < N ;  i++) f[i] =  i;
    ms(in,0);
    ms(out,0);
}
int n ;
set<int>se;
bool Euler()
{
    int a,b;
    a=b=0;
    set<int>::iterator it;
    for ( it = se.begin() ;it!=se.end() ; it++)
    {
	int i = *it;
	if (in[i]==out[i]+1)a++;
	else if (out[i]==in[i]+1) b++;
	else if (out[i]!=in[i]) return false;
    }
    if (a+b==0||(a==1&&b==1)) return true;
    return false;
}
int main()
{
	#ifndef  ONLINE_JUDGE 
	freopen("code/in.txt","r",stdin);
  #endif
	int T;
	cin>>T;
	while (T--)
	{
	    init();
	    scanf("%d",&n);
	    se.clear();
	    for ( int i = 0 ; i < n ; i++)
	    {
		char st[1005];
		scanf("%s",st);
		int len = strlen(st);
		int u = st[0]-'a';
		int v = st[len-1]-'a';
		merge(u,v);
		out[u]++;
		in[v]++;
		se.insert(v);
		se.insert(u);
	    }
	    int cnt = 0 ;
	    bool die = false;
	    for (set<int>::iterator it = se.begin() ; it!=se.end() ; it++)
	    {
		if (f[*it]==*it) cnt++;
		if (cnt>1)
		{
		    die = true;
		    break;
		}
	    }
	    if (!Euler()) die = true;
	    if (die)
	    {
		puts("The door cannot be opened.");
	    }
	    else
	    {
		puts("Ordering is possible.");
	    }
	}
  #ifndef ONLINE_JUDGE  
  fclose(stdin);
  #endif
    return 0;
}

** **