【CF 508D】 Tanya and Password (判欧拉路+输出欧拉路径)
n个串构成长n+2的密码 如果某个串后两个字符和一个串前两个字符相同 可由这两个字符拼接 即以某个串(长3)开始 构成一条串 往后均是拼接起的 即+(n-1)个字符 才可达到n+2
并查集判图联通
存在入度出度差大于1则不可构成欧拉路
入度出度都为0则为欧拉回路(起点任意)
入度出度差1的点个数为2则为欧拉通路(出度大于入度的点为起点) 个数大于2也不可构成欧拉路
dfs输出欧拉路径 回溯和递推两种 回溯内存14K+ 递推版2K+
代码如下:
#include <bits/stdc++.h>
using namespace std;
struct Edge
{
int v,next;
};
Edge eg[233333];
int pre[6666];//并查集
int id[6666],val[6666];//id:两字符构成串映射的点 val:点映射的单词
int head[6666];
int in[6666];//度
int tp,ptp,n,st;//tp:边下标 ptp:点下标 n:串数 st:图遍历起点
void Add(int u,int v)
{
eg[tp].v = v;
eg[tp].next = head[u];
head[u] = tp++;
}
int to(int x)
{
if(x >= '0' && x <= '9') return x-'0';
if(x >= 'a' && x <= 'z') return x-'a'+10;
return x-'A'+36;
}
int getpre(char *s)
{
return to(s[0])*100+to(s[1]);
}
int getpost(char *s)
{
return to(s[1])*100+to(s[2]);
}
int Find(int x)
{
return (pre[x] == x)? pre[x] : (pre[x] = Find(pre[x]));
}
void init()
{
scanf("%d",&n);
tp = ptp = 0;
memset(head,-1,sizeof(head));
memset(id,-1,sizeof(id));
memset(in,0,sizeof(in));
char ch[4];
for(int i = 0; i < n; ++i)
{
scanf("%s",ch);
int u = getpre(ch);
int v = getpost(ch);
if(id[u] == -1)
{
id[u] = ptp;
val[ptp] = u;
pre[ptp] = ptp++;
}
if(id[v] == -1)
{
id[v] = ptp;
val[ptp] = v;
pre[ptp] = ptp++;
}
Add(id[u],id[v]);
int k = Find(id[u]);
int r = Find(id[v]);
if(k > r) pre[k] = r;
else pre[r] = k;
in[id[v]]++;
in[id[u]]--;
}
}
int tochar(int x)
{
if(x < 10) return x+'0';
if(x < 36) return x-10+'a';
return x-36+'A';
}
//判是否联通且构成欧拉路
bool ok()
{
int root = Find(0);
int cnt = 0;
st = 0;
for(int i = 0; i < ptp; ++i)
{
//printf("%c%c %d\n",tochar(val[i]/100),tochar(val[i]%100),in[i]);
if(root != Find(i)) return false;
if(in[i] > 1 || in[i] < -1) return false;
if(in[i])
{
cnt++;
if(in[i] < 0) st = i;
if(cnt > 2) return false;
}
}
return true;
}
stack <char> ans;
//递推版
//stack <int> s;
//
//void dfs()
//{
// s.push(st);
//
// while(!s.empty())
// {
// st = s.top();
// if(head[st] != -1)
// {
// s.push(eg[head[st]].v);
// head[st] = eg[head[st]].next;
// }
// else
// {
// ans.push(tochar(val[st]%100));
// s.pop();
// }
// }
//}
//回溯版
void dfs(int x)
{
for(int i = head[x]; i != -1; i = head[x])
{
head[x] = eg[i].next;
dfs(eg[i].v);
}
ans.push(tochar(val[x]%100));
}
int main()
{
init();
if(ok())
{
puts("YES");
//printf("%d\n",st);
printf("%c",tochar(val[st]/100));
dfs(st);
while(!ans.empty())
{
putchar(ans.top());
ans.pop();
}
//putchar(tochar(val[st]/100));
puts("");
}else puts("NO");
return 0;
}