Tanya and Password【Codeforces 508 D】【欧拉通路+输出路径】

本文详细解析了Codeforces Round #288 (Div.2) D题的欧拉通路算法实现,通过栈维护访问顺序,解决了中断问题,实现了正确的欧拉通路输出。特别讨论了特判情况和具体代码实现细节。

Codeforces Round #288 (Div. 2) D

欧拉通路好题!!!

一开始的时候,我想了一下,不知道该怎么解决一个“中断”的问题(可能微机学多了,用了这个名词解释哈哈哈)。

如图类型:

  所以,我们可以拿栈维护一下,重点就是栈,其他XJB操作都是不得正解的!!!

  譬如,我们访问到了,我们访问下一个结点,然后把后继所有访问完了,也就是把后继所有的都是进栈了。于是,是不是满足了我们所要的输出欧拉通路的作用了!!!太巧了,好!

  当然,不要忘记特判,假如大家都是"aaa"的时候,实际上我们要给起点定义的哟~
 

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <unordered_map>
#include <unordered_set>
#define _ABS(x, y) ( x > y ? (x - y) : (y - x) )
#define lowbit(x) ( x&( -x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define efs 1e-7
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
#define MP(a, b) make_pair(a, b)
using namespace std;
typedef unsigned long long ull;
typedef unsigned int uit;
typedef long long ll;
const int maxN = 4e5 + 7;
int N, In_du[maxN] = {0}, Out_du[maxN] = {0}, tot = 0, root[maxN];
inline int fid(int x) { return x == root[x] ? x : root[x] = fid(root[x]); }
char s[maxN][4], ch[maxN][2];
string tmp;
unordered_map<string, int> Hash_mp;
inline int Hash_id(char fir, char sec)
{
    tmp.clear(); tmp += fir; tmp += sec;
    if(Hash_mp[tmp]) return Hash_mp[tmp];
    else
    {
        ch[++tot][0] = fir; ch[tot][1] = sec;
        return Hash_mp[tmp] = tot;
    }
}
int head[maxN], cnt;
struct Eddge
{
    int nex, to;
    Eddge(int a=-1, int b=0):nex(a), to(b) {}
}edge[maxN << 1];
inline void addEddge(int u, int v) { edge[cnt] = Eddge(head[u], v); head[u] = cnt++; }
stack<char> ans;
stack<int> S;
void dfs(int st)
{
    S.push(st);
    int u, v;
    while(!S.empty())
    {
        u = S.top();
        if(~head[u])
        {
            v = edge[head[u]].to;
            head[u] = edge[head[u]].nex;
            S.push(v);
        }
        else
        {
            ans.push(ch[u][1]);
            S.pop();
        }
    }
}
inline void init()
{
    tot = 0;
    for(int i=0; i<=(N << 1); i++)
    {
        head[i] = -1;
        root[i] = i;
    }
}
int main()
{
    scanf("%d", &N);
    init();
    for(int i=1, u, v, fu, fv; i<=N; i++)
    {
        scanf("%s", s[i]);
        u = Hash_id(s[i][0], s[i][1]); v = Hash_id(s[i][1], s[i][2]);
        Out_du[u]++; In_du[v]++;
        addEddge(u, v);
        fu = fid(u); fv = fid(v);
        if(fu ^ fv) root[fu] = fv;
    }
    int KK = 0;
    for(int i=1; i<=tot; i++) KK += (i == fid(i));
    if(KK ^ 1) { printf("NO\n"); return 0; }
    bool flag = true;
    int st = 0, nono = 0;
    for(int i=1; i<=tot; i++)
    {
        if(In_du[i] == Out_du[i]) continue;
        if(Out_du[i] - In_du[i] == 1)
        {
            if(st)
            {
                flag = false;
                break;
            }
            else st = i;
        }
        else if(Out_du[i] - In_du[i] == -1)
        {
            if(++nono > 1) { flag = false; break; }
        }
        else { flag = false; break; }
    }
    if(!flag) { printf("NO\n"); return 0; }
    if(!st) st = 1; //全相同情况
    dfs(st);
    ans.push(ch[st][0]);
    printf("YES\n");
    while(!ans.empty())
    {
        printf("%c", ans.top());
        ans.pop();
    }
    printf("\n");
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wuliwuliii

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值