P1341 无序字母对 欧拉路径

版权声明:转载请注明出处 https://blog.csdn.net/qq_43590432/article/details/88562523

题目:P1341 无序字母对

题目描述

给定n个各不相同的无序字母对(区分大小写,无序即字母对中的两个字母可以位置颠倒)。请构造一个有n+1个字母的字符串使得每个字母对都在这个字符串中出现。

输入输出格式

输入格式:

第一行输入一个正整数n。

以下n行每行两个字母,表示这两个字母需要相邻。

输出格式:

输出满足要求的字符串。

如果没有满足要求的字符串,请输出“No Solution”。

如果有多种方案,请输出前面的字母的ASCII编码尽可能小的(字典序最小)的方案


要求:构造一个有n+1个字母的字符串使得每个字母对都在这个字符串中出现。

题解:将每个字母看成一个点,每对字母看成一条边,题目要求就变成了,找到一条路径,使其能经过所有边并且每条边只走一次(保证了只有n+1个字母),题目很明显变成了一个求欧拉路径的题。

欧拉回路:奇数度的点为0;欧拉路径:奇数点的度为2;

#include<bits/stdc++.h>
using namespace std;

int n;
vector<int > g[130];
int du[130]={0};
int st=130;
int ans=0;
int vis[130][130]={0};
int path[2000];
int k=0;

void dfs(int i){
	for(int j=0;j<g[i].size();j++){
		int a=g[i][j];
		if(!vis[i][a]){//找到第一个未走过的路,字典序最小 
			vis[i][a]=vis[a][i]=1;//标记路走过 
		    dfs(a);
		}
	}
	path[++k]=i;//记录路径 
}
int main(){
	std::ios::sync_with_stdio(false);
	std::cin.tie(0);
	std::cout.tie(0);

	cin>>n;
	char a[2];
	for(int i=0;i<n;i++){
		cin>>a;
		du[a[0]]++,du[a[1]]++;//记录每个节点的度 
		g[a[0]].push_back(a[1]);
		g[a[1]].push_back(a[0]);
	}
	
	for(int i=65;i<130;i++) sort(g[i].begin(),g[i].end());//将每个点连接边的终点 按字典序排序 
	
	for(int i=65;i<130;i++){
		if(du[i]%2==1){
			if(!ans)st=i;//第一个奇数点为字典序最小的点,起点 
			ans++;//奇数点个数 
		}
	}
	//奇数点为2则存在欧拉路径,奇数点为0则存在欧拉回路 
	if(ans!=0&&ans!=2){
		cout<<"No Solution"<<endl;
		return 0;
	}
	if(!ans){//是欧拉回路,则需要再找起点 
		for(int i=65;i<130;i++){
			if(du[i]) { st=i; break;}
		}
	}
	dfs(st);//深搜起点,找到路径 
	for(int i=k;i>=0;i--){//逆序输出 
		cout<<(char)path[i];
	}
	cout<<endl;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_43590432/article/details/88562523
今日推荐