[洛谷P1341]无序字母对

题目大意:见原题目描述,说的很清楚。

算法:图论、欧拉路径

思路:题目数据中没有重复条件,因此成功得到解有两种可能。①n个点,n条路径,形成欧拉回路(没有奇数点);②n+1个点,n条路径,形成欧拉路径(只有2个奇数点)。因此先判断是否有解,如果有就用dfs搜欧拉路径(回路)即可。

我这里给每个字母都进行了编号,使用时可以编号和原字母互相转换。

C++ Code:

 

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#define N 3000
using namespace std;
int n,m=0;
bool b[N][N];
int ctoi[N],hasR[N],odd1,odd2,odds;
char itoc[N],s[3],inp[N],ans[N];
void dfs(int now,int p){
	ans[p]=itoc[now];
	if(p>n){
		printf("%s",ans+1);
		exit(0);
	}
	for(int i=1;i<=m;i++)
	if(b[now][ctoi[inp[i]]]){
		b[now][ctoi[inp[i]]]=b[ctoi[inp[i]]][now]=false;
		dfs(ctoi[inp[i]],p+1);
		b[now][ctoi[inp[i]]]=b[ctoi[inp[i]]][now]=true;
	}
	ans[p]='\0';
}
int main(){
	scanf("%d",&n);
	memset(ctoi,0,sizeof(ctoi));
	memset(itoc,0,sizeof itoc);
	memset(hasR,0,sizeof hasR);
	memset(b,0,sizeof b);
	for(int i=1;i<=n;i++){//读入、处理,将每个字母编号
		scanf("%s",s);
		if(!ctoi[s[0]]){
			m++;
			ctoi[s[0]]=m;
			itoc[m]=s[0];
			inp[m]=s[0];
		}
		if(!ctoi[s[1]]){
			m++;
			ctoi[s[1]]=m;
			itoc[m]=s[1];
			inp[m]=s[1];
		}
		b[ctoi[s[1]]][ctoi[s[0]]]=b[ctoi[s[0]]][ctoi[s[1]]]=true;
		hasR[ctoi[s[0]]]++;
		hasR[ctoi[s[1]]]++;
	}
	sort(inp+1,inp+m+1);
	odds=0;
	for(int i=1;i<=m;i++)
	if(hasR[i]%2){
		odds++;
		if(odds==1)odd1=i;else
		if(odds==2)odd2=i;else{
			printf("No Solution");
			return 0;
		}
	}
	if(odds!=0&&odds!=2){
		printf("No Solution");
		return 0;
	}
	int start;
	if(odds==2){
		if(itoc[odd1]<itoc[odd2])start=odd1;else
		start=odd2;
	}
	else
	start=ctoi[inp[1]];
	memset(ans,'\0',sizeof ans);
	dfs(start,1);
	return 0;
}

 

转载于:https://www.cnblogs.com/Mrsrz/p/6985941.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值