本题地址: http://www.luogu.org/problem/show?pid=1341
题目描述
给定n个各不相同的无序字母对(区分大小写,无序即字母对中的两个字母可以位置颠倒)。请构造一个有n+1个字母的字符串使得每个字母对都在这个字符串中出现。
输入输出格式
输入格式:
第一行输入一个正整数n。
以下n行每行两个字母,表示这两个字母需要相邻。
输出格式:
输出满足要求的字符串。
如果没有满足要求的字符串,请输出“No Solution”。
如果有多种方案,请输出前面的字母的ASCII编码尽可能小的(字典序最小)的方案
输入输出样例
输入样例#1:
4 aZ tZ Xt aX
输出样例#1:
XaZtX
说明
【数据规模与约定】
不同的无序字母对个数有限,n的规模可以通过计算得到。
思路
容易看出这是一个欧拉图。然而我思索了良久也不会写一个图的算法,只好用深搜和回溯写,又然而数据是在太水,竟然过了!
P1:我用到了重边的判断。
P2:要求按字典序输出,那么搜索的时候就从字典序最小的那一个开始搜索。
var a:array['A'..'z','A'..'z'] of longint; du:array['A'..'z'] of longint; ans:array[0..100000] of char; n:longint; procedure dfs(u:char;tot:longint); var j:longint;k:char; begin ans[tot]:=u; if tot=n+1 then begin for j:=1 to n+1 do write(ans[j]); writeln; halt; end; for k:='A' to 'z' do if a[u,k]<>0 then begin dec(a[u,k]); dec(a[k,u]); dfs(k,tot+1); inc(a[k,u]); inc(a[u,k]); //回溯 end; end; procedure change; begin fillchar(a,sizeof(a),0); fillchar(du,sizeof(du),0); end; procedure init; var i:longint;one,two:char; begin readln(n); for i:=1 to n do begin readln(one,two); inc(a[one,two]); inc(a[two,one]); inc(du[one]); inc(du[two]); end; end; procedure main; var x:char;one,two:char; begin for x:='A' to 'z' do if (du[x] mod 2=1) then begin if two<>' ' then begin writeln('No Solution'); halt; end; if (one<>' ')and(two=' ') then two:=x; if one=' ' then one:=x; end; if (one<>' ')and(two=' ') then begin writeln('No Solution'); halt; end; //考虑到可能有重边的情况,one和two是两个备用字符串 if (one=' ')and(two=' ') then begin for x:='A' to 'z' do if du[x]<>0 then break; dfs(x,1); end else if one>two then dfs(two,1) else dfs(one,1); //一切为了字典序 end; begin change; init; main; end.