[洛谷1314]无序字母对

本题地址: 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.
View Code

 

posted on 2015-08-19 21:43  川汉唐  阅读(715)  评论(1)    收藏  举报

导航