在圖中找一個環使得每條邊都在環上出現剛好一次。ios
要注意的地方好多啊優化
每條邊剛好出現一次!!!spa
條件:每一個點偶度 / 入度=出度code
方法就是套圈法啦get
而後本題自環是合法的,若是20000個(1,1)邊的話會被卡成\(O(n^2)\),因此加上當前弧優化string
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <set> #include <map> using namespace std; typedef long long ll; #define fir first #define sec second const int N = 2e5+5, inf = 1e9+5; inline int read() { char c=getchar(); int x=0,f=1; while(c<'0'||c>'9') {if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();} return x*f; } int type, n, m, u, v; struct edge {int v, ne;} e[N<<1]; int cnt = 1, h[N]; namespace undir { inline void ins(int u, int v) { e[++cnt] = (edge) {v, h[u]}; h[u] = cnt; e[++cnt] = (edge) {u, h[v]}; h[v] = cnt; } int de[N], st[N], top, mark[N<<1]; void dfs(int u) { //if(++t % 1000 == 0) printf("t %d\n", t); for(int &i=h[u]; i; i=e[i].ne) if(!mark[i]) { mark[i] = mark[i^1] = 1; int j = i; dfs(e[i].v); st[++top] = j&1 ? -((j-1)>>1) : j>>1; } } void solve() { for(int i=1; i<=m; i++) u = read(), v = read(), ins(u, v), de[u]++, de[v]++; for(int i=1; i<=n; i++) if(de[i] & 1) {puts("NO"); return;} int u = 1; while(u <=n && !de[u]) u++; dfs(u); if(top != m) {puts("NO"); return;} puts("YES"); while(top) printf("%d ", st[top--]); } } namespace dir { inline void ins(int u, int v) { e[++cnt] = (edge) {v, h[u]}; h[u] = cnt; } int ind[N], outd[N], st[N], top, mark[N]; void dfs(int u) { for(int &i=h[u]; i; i=e[i].ne) if(!mark[i]) { mark[i] = 1; int j = i; dfs(e[i].v); st[++top] = j-1; } } void solve() { for(int i=1; i<=m; i++) u = read(), v = read(), ins(u, v), outd[u]++, ind[v]++; for(int i=1; i<=n; i++) if(ind[i] != outd[i]) {puts("NO"); return;} int u = 1; while(u <=n && !outd[u]) u++; dfs(u); if(top != m) {puts("NO"); return;} puts("YES"); while(top) printf("%d ", st[top--]); } } int main() { freopen("in.in", "r", stdin); type = read(); n = read(); m = read(); if(type == 1) undir::solve(); else dir::solve(); }