悠木皆守学会了一种古老的文字。
该文字共有M 种不同的字符1; 2; : : : ; M。一个简单词由两个字符组
成(这两个字符可以相同)。一个复杂词由若干个简单词组合而成;具体地,
对于一个词(可以是简单词或复杂词)a1a2 · · · al 和另一个简单词b1b2,如果
al = b1,那么它们可以组合成一个复杂词a1a2 · · · alb2(因为al = b1 所以b1
被去掉了)。例如,如果用英文字母来表示字符,ab 和bc 可以组合成abc。
现在,悠木皆守有N 个简单词,第i 个词是uivi,他想用每个词恰好一次
(顺序任意),将它们组合起来形成一个复杂词(注意,如果输入的简单词有相
同的,那么也要每个用一次)。
另外再输入一个参数T。若T = 1,则一个简单词的两个字符可以交换顺
序,即uivi 可以当做viui 来使用(但只能使用这两个中的一个);如果T = 2,
则一个简单词的两个字符不能交换顺序,只能作为uivi 使用。
这道题首先数据范围1e5 的 2e5,如果n ^ 2的建图肯定会T,那么可以考虑把每个单词看作边,把数字看作点,这样就变成了求一个路径能够恰好覆盖所有边一次的,那么就变成的欧拉路。
呃呃呃考虑如何快速的求欧拉回路,这里有一篇题解讲的非常好https://www.cnblogs.com/ivorysi/p/5745005.html
这里有个套圈法,每次先走到一个不能再走的废物节点,然后把边/点压进一个栈来存储,这样一直找,最后倒序把栈中元素输出就是答案了
判断不合法:
对于无向图,首先图要联通,然后要判断奇点,若数量 > 2 或 =1,那么不合法
要不然就有两个奇点或没有,有两个的时候一个作为出发点,一个作为终点
没有的时候还是欧拉回路,随便找一个点作为起点即可
对于有向图,图还是要联通,但是判断图联通不能随便选出发点了,要在找到合法出发点再进行dfs记录数量,像无向图一样使用套圈法记录回路即可
代码
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 8e5 + 5;
int T, n, m;
int read() {
int rt = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9') {
if (ch == '-') f = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9') {
rt = (rt << 1) + (rt << 3) + ch - '0';
ch = getchar();
}
return rt * f;
}
int cnt, nxt[maxn], tot = 1, tov[maxn], head[maxn], id[maxn];
int dgr[maxn], tmp[maxn], stk[maxn], s, top = 0, in[maxn], out[maxn];
bool vis[maxn], ar[maxn];
struct Node {
int u, v;
}a[maxn];
void add(int u, int v, int w) {
tot++;
tov[tot] = v;
nxt[tot] = head[u];
head[u] = tot;
id[tot] = w;
}
void dfs(int u) {
vis[u] = 1;
cnt++;
for (int i = head[u]; i; i = nxt[i]) {
int v = tov[i];
if (vis[v]) continue;
dfs(v);
}
}
void dfs1(int u, int e) {
for (int i = head[u]; i; i = nxt[i]) {
int v = tov[i];
if (vis[i]) continue;
vis[i] = vis[i ^ 1] = 1;
dfs1(v, i);
}
stk[++top] = id[e];
}
void dfs2(int u, int e) {
if (!ar[u]) ar[u] = 1, cnt++;
for (int i = head[u]; i; i = nxt[i]) {
int v = tov[i];
if (vis[i]) continue;
vis[i] = 1;
dfs2(v, i);
}
stk[++top] = id[e];
}
int main() {
freopen("merge.in","r",stdin);
freopen("merge.out","w",stdout);
T = read(), m = read(), n = read();
if (T == 1) {
int cnt1 = 0;
for (int i = 1; i <= n; i++) {
a[i].u = read(), a[i].v = read();
if (!vis[a[i].u]) vis[a[i].u] = 1, cnt1++;
if (!vis[a[i].v]) vis[a[i].v] = 1, cnt1++;
add(a[i].u, a[i].v, i);
add(a[i].v, a[i].u, -i);
dgr[a[i].u]++;
dgr[a[i].v]++;
}
for (int i = 1; i <= tot; i++) vis[i] = 0;
cnt = 0;
dfs(a[1].u);
if (cnt != cnt1) {
puts("NO");
return 0;
}
for (int i = 1; i <= m; i++) vis[i] = 0;
int num = 0;
for (int i = 1; i <= n; i++) {
if ((dgr[a[i].u] & 1) && !vis[a[i].u]) tmp[++num] = a[i].u, vis[a[i].u] = 1;
if ((dgr[a[i].v] & 1) && !vis[a[i].v]) tmp[++num] = a[i].v, vis[a[i].v] = 1;
}
if (num == 0) {
s = a[1].u;
} else if (num == 2) {
s = tmp[1];
} else {
puts("NO");
return 0;
}
for (int i = 1; i <= tot; i++) vis[i] = 0;
dfs1(s, 0);
puts("YES");
for (int i = top - 1; i >= 1; i--) {
printf("%d", stk[i]);
if (i != 1) printf(" ");
}
} else {
int cnt1 = 0;
for (int i = 1; i <= n; i++) {
a[i].u = read(), a[i].v = read();
if (!vis[a[i].u]) vis[a[i].u] = 1, cnt1++;
if (!vis[a[i].v]) vis[a[i].v] = 1, cnt1++;
add(a[i].u, a[i].v, i);
in[a[i].v]++, out[a[i].u]++;
}
cnt = 0;
int num = 0;
bool flag = 0;
for (int i = 1; i <= m; i++) vis[i] = 0;
for (int i = 1; i <= n; i++) {
if (in[a[i].u] != out[a[i].u]) {
if (in[a[i].u] != out[a[i].u] + 1 && in[a[i].u] != out[a[i].u] - 1) flag = 1;
if (!vis[a[i].u])
tmp[++num] = a[i].u, vis[a[i].u] = 1;
}
if (in[a[i].v] != out[a[i].v]) {
if (in[a[i].v] != out[a[i].v] + 1 && in[a[i].v] != out[a[i].v] - 1) flag = 1;
if (!vis[a[i].v])
tmp[++num] = a[i].v, vis[a[i].v] = 1;
}
}
for (int i = 1; i <= tot; i++) vis[i] = 0;
if (flag) {
puts("NO");
return 0;
}
if (num == 0) {
s = a[1].u;
} else if (num == 2) {
if (in[tmp[1]] == out[tmp[1]] - 1) s = tmp[1];
if (in[tmp[2]] == out[tmp[2]] - 1) s = tmp[2];
if (in[tmp[1]] == out[tmp[1]] - 1 && in[tmp[2]] == out[tmp[2]] - 1) flag = 1;
if (in[tmp[1]] == out[tmp[1]] + 1 && in[tmp[2]] == out[tmp[2]] + 1) flag = 1;
} else {
puts("NO");
return 0;
}
if (flag) {
puts("NO");
return 0;
}
dfs2(s, 0);
if (cnt != cnt1) {
puts("NO");
return 0;
}
puts("YES");
for (int i = top - 1; i >= 1; i--) {
printf("%d", stk[i]);
if (i != 1) printf(" ");
}
}
return 0;
}