题目链接
记住的是这道题是欧拉回路,而不是欧拉通路,两者是有本质上的差别的。
欧拉回路与欧拉通路相同,主要原理还是在于一个栈的巧上面,这个栈真的用的很巧,也就是相当于,我们虽然有其他的路径可以走,而且我们尽管现在是随机跑的,可能会忽略一些边,使得欧拉回路不完整,但是呢,我们用栈就可以很好的避免了这个问题了哟。
我们现在虽然是往下走了(而且强调一个随机性),但是呢,我们之后回溯回来再走的时候,其实还是会把原来的路径打开一个缺口,把现在的这条链放进去就是了。
stack在欧拉通路和欧拉回路中真好用!!!
我的code中,打注释掉的部分是欧拉通路,另外的是欧拉回路部分。看需求了。
#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 = 1e5 + 7;
int op, N, M, head[maxN], cnt;
struct Eddge
{
int nex, to, id;
Eddge(int a=-1, int b=0, int c=0):nex(a), to(b), id(c) {}
}edge[maxN << 2];
inline void addEddge(int u, int v, int id)
{
edge[cnt] = Eddge(head[u], v, id);
head[u] = cnt++;
}
inline void _add(int u, int v, int id) { addEddge(u, v, id); addEddge(v, u, -id); }
stack<int> st, ans;
int In_du[maxN] = {0}, Out_du[maxN] = {0}, du[maxN] = {0}, root[maxN];
inline int fid(int x) { return x == root[x] ? x : root[x] = fid(root[x]); }
bool vis_line[maxN << 2] = {false}, vis[maxN] = {false};
stack<int> pre[maxN];
inline void un_dir()
{
for(int i=1, u, v, fu, fv; i<=M; i++)
{
scanf("%d%d", &u, &v);
vis[u] = vis[v] = true;
_add(u, v, i);
du[u]++; du[v]++;
fu = fid(u); fv = fid(v);
if(fu ^ fv) root[fu] = fv;
}
int num_root = 0;
for(int i=1; i<=N; i++) num_root += (vis[i] && i == fid(i));
if(num_root > 1) { printf("NO\n"); return; }
int S = 0, tri_num = 0;
for(int i=1; i<=N; i++)
{
if(du[i] & 1)
{
// S = i;
// tri_num ++;
printf("NO\n"); return;
}
}
// if(tri_num > 2) { printf("NO\n"); return; }
if(!S)
{
S = 1;
while(!vis[S] && S <= N) S++;
if(S > N) { printf("YES\n"); return; }
}
st.push(S);
int u, v;
while(!st.empty())
{
u = st.top();
if(~head[u])
{
while(~head[u] && vis_line[head[u]])
{
head[u] = edge[head[u]].nex;
}
if(head[u] == -1) continue;
v = edge[head[u]].to;
pre[v].push(edge[head[u]].id);
vis_line[head[u]] = vis_line[head[u] ^ 1] = true;
head[u] = edge[head[u]].nex;
st.push(v);
}
else
{
if(!pre[u].empty())
{
ans.push(pre[u].top());
pre[u].pop();
}
st.pop();
}
}
printf("YES\n");
while(!ans.empty())
{
printf("%d", ans.top());
ans.pop();
if(!ans.empty()) printf(" ");
else printf("\n");
}
}
inline void dir()
{
for(int i=1, u, v, fu, fv; i<=M; i++)
{
scanf("%d%d", &u, &v);
vis[u] = vis[v] = true;
addEddge(u, v, i);
In_du[v]++; Out_du[u]++;
fu =fid(u); fv = fid(v);
if(fu ^ fv) root[fu] = fv;
}
int num_root = 0;
for(int i=1; i<=N; i++) num_root += (vis[i] && i == fid(i));
if(num_root > 1) { printf("NO\n"); return; }
int S = 0, E = 0;
for(int i=1; i<=N; i++)
{
if(Out_du[i] == In_du[i]) continue;
printf("NO\n");
return;
// if(Out_du[i] == In_du[i] + 1)
// {
// if(S) { printf("NO\n"); return; }
// S = i;
// }
// else if(Out_du[i] == In_du[i] - 1)
// {
// if(E) { printf("NO\n"); return; }
// E = i;
// }
}
if(!S)
{
S = 1;
while(!vis[S] && S <= N) S++;
if(S > N) { printf("YES\n"); return; }
}
int u, v;
st.push(S);
while(!st.empty())
{
u = st.top();
if(~head[u])
{
v = edge[head[u]].to;
pre[v].push(edge[head[u]].id);
head[u] = edge[head[u]].nex;
st.push(v);
}
else
{
if(!pre[u].empty())
{
ans.push(pre[u].top());
pre[u].pop();
}
st.pop();
}
}
printf("YES\n");
while(!ans.empty())
{
printf("%d", ans.top());
ans.pop();
if(!ans.empty()) printf(" ");
else printf("\n");
}
}
inline void init()
{
cnt = 0;
for(int i=1; i<=N; i++)
{
head[i] = -1;
root[i] = i;
}
}
int main()
{
scanf("%d%d%d", &op, &N, &M);
init();
if(op == 1) un_dir();
else dir();
return 0;
}