luogu#P1341 无序字母对

题意:

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

解法:

一道欧拉回路的模板题。将每个字母两两之间连一条无向边,然后求欧拉回路(保证字典序最小)。

#include<iostream>
#include<stack>
#define N 60
#define tint(_) (int(_-'A'))
#define tchar(_) (char(_+'A'))
using namespace std;
bool e[N][N]={0};
int n,d[N],f[N],s;
stack<int> st;

void out();
void dfs(int x);
void finds();
int fnd(int x);
void uni(int x,int y);
bool check();
void init();
int main()
{
	init();
	if(check())
	{
		cout<<"No Solution";
		return 0;
	}
	finds();
	dfs(s);
	out();
	return 0;
}
void out()
{
	while(!st.empty())
	{
		cout<<tchar(st.top());
		st.pop();	
	}
}
void init()
{
	cin>>n;
	for(int i=0;i<=N;i++)
		f[i]=i;
	for(int i=1;i<=n;i++)
	{
		char zu,zv;
		int u,v;
		cin>>zu>>zv;
		u=tint(zu); v=tint(zv);
		d[u]++; d[v]++;
		uni(u,v);
		e[u][v]=1;
		e[v][u]=1;
	}	
}
bool check()
{
	int j=0,now=0,fa;
	for(int i=0;i<=N;i++)
		if(d[i]%2==1)
			j++;
	if(j&&j!=2)
		return 1;
	while(!d[now++]);
	now--;
	fa=fnd(now);
	for(int i=now+1;i<=N;i++)
		if(d[i]&&fnd(i)!=fa)
			return 1;
	return 0;
}
int fnd(int x)
{
	if(f[x]==x)
		return x;
	return f[x]=fnd(f[x]);
}
void uni(int x,int y)
{
	if(fnd(x)!=fnd(y))
		f[fnd(x)]=fnd(y);
}
void finds()
{
	s=0;
	for(int i=0;i<=N;i++)
		if(d[i]%2==1)
		{
			s=i;
			break;
		}
	if(n==1)
		s=0;
	if(!s)
		for(int i=0;i<=N;i++)
			if(d[i])
			{
				s=i;
				return;
			}
}
void dfs(int x)
{
	for(int i=0;i<=N;i++)
		if(e[x][i])
		{
			e[x][i]=0;
			e[i][x]=0;
			dfs(i);
		}
	st.push(x);
}
posted @ 2019-10-21 21:34  nenT  阅读(113)  评论(0)    收藏  举报