码迷,mamicode.com
首页 > 其他好文 > 详细

无序字母对

时间:2015-08-19 23:27:06      阅读:272      评论:0      收藏:0      [点我收藏+]

标签:

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

 

无序字母对

标签:

原文地址:http://www.cnblogs.com/yangqingli/p/4743559.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!