uva 10129

本文介绍了一种基于欧拉路径的经典算法问题,针对一组字符串,验证它们之间是否存在欧拉路径。通过对字符串首尾字符的分析,构建有向图并判断其是否满足欧拉路径条件,包括连通性、奇数度顶点的数量以及顶点的出入度等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原题

欧拉路径经典问题, 

给一些字符串, 要求验证字符串之间是否存在欧拉路径

题意能化简就化简, 其实字符串只看首尾字母即可, 各代表一个顶点, 一个字符串就是一条边

然后就是欧拉路径的通解法, 

对于无向图只需要验证连通性, 并且奇数度的顶点只能有2个(一个起点一个终点形成欧拉路径) 或 0个(形成欧拉回路)

对于本题中的有向图, 除了连通性, 除了起点和终点之外, 各个顶点的出度和入度必须相等

并且起点的出度一定比入度大1, 终点的入度比出度大1( 形成欧拉路径)

还有一种特殊情况就是所有顶点的出度和入度相等( 形成欧拉回路 ) 

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string>
#include <vector>
#include <set>
#include <stack>
#include <queue>
#include <deque>
#include <map>
#include <list>
#include <cassert>
#include <iomanip>

using namespace std;
const int MAXN = 26;
const int BASE = 10;
typedef long long LL;
/*
uva 10129
关键: 	1. 对于有向图, Euler Path 除了起点和终点之外, 其他点的出度和入度必须相等, 
而且起点的出度恰好比入度大1, 终点的入度恰好比出度大1 
或者形成 Euler Circuit, 即所有点的出度和入度都相等 
		2. 对于无向图(此题为有向图), Euler Path 奇数度的点(奇点)个数等于0或2即可 
 		3. 要考虑到只有一个word的情况 
		
*/

int T, n, cnt;
int Edge[MAXN][MAXN];
int in[MAXN],out[MAXN];

void DFS(int v){
	for(int i=0; i<MAXN; i++){
		if( Edge[v][i] ){
			cnt++;
			Edge[v][i]--;
			DFS(i);
		}
	}
}

int main(){
	cin >> T;
	string str;
	while( T-- ){
		bool res = true;
		memset(Edge,0,sizeof(Edge));
		memset(in,0,sizeof(in));
		memset(out,0,sizeof(out));
		cin >> n;
		for(int i=0; i<n; i++){
			cin >> str;
			out[*str.rbegin()-'a']++;
			in[*str.begin()-'a']++;
			Edge[*str.rbegin()-'a'][*str.begin()-'a']++;
		}
		int notEqual = 0;
		cnt = -1;
		for(int i=0; i<MAXN; i++){
			if( in[i] != out[i] ){
				notEqual++;
				if( in[i]-out[i]!=1 && out[i]-in[i]!=1 ){	//是起点或终点, 不算notEqual 
//					 cout << "false1" << endl;
					 res = false;
					 break;
				}else notEqual--;
				if( out[i]-in[i]==1 ){
					cnt = 0;
					DFS(i);
				}
			}
		}
		if( res && cnt==-1 ){
			for(int i=0; i<MAXN; i++){
				if( out[i]>0 ){
					cnt = 0;
					DFS(i);
					break;
				}
			}
		}
		if( res && notEqual!=0 || cnt!=n   ){	// 无欧拉回路 或 不连通
//			cout << "false2" << endl; 
			res = false;
		}
		if( res ) cout << "Ordering is possible." << endl;
		else cout << "The door cannot be opened." << endl;
	}
	return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值