Codeforces 1186F. Vus the Cossack and a Graph(歐拉回路)
阿新 • • 發佈:2020-08-07
https://codeforces.com/contest/1186/problem/F
題解:
看到這樣的限制不難聯想到歐拉回路(一看就是倒著造的題)。
對每個聯通塊分開考慮。
考慮如果所有點都是偶數,那麼隨便找一個歐拉回路,交叉染色即可。
如果有奇點,建一個新點,奇點向新建中轉點連虛邊,然後跑一條迴路。
虛邊會把路徑劃分成若干段,對每一段都交叉染色,特別地,保證每一段最左最右的邊一定選,因為中間的點必須一選一不選,而旁邊的點度數本來是奇數,可以有一次多選的機會。
Code:
#include<bits/stdc++.h> #define fo(i, x, y) for(int i = x, _b = y; i <= _b; i ++) #define ff(i, x, y) for(int i = x, _b = y; i < _b; i ++) #define fd(i, x, y) for(int i = x, _b = y; i >= _b; i --) #define ll long long #define pp printf #define hh pp("\n") using namespace std; const int N = 4e6 + 5; int fi[N], to[N], nt[N], tot = 1; void link(int x, int y) { nt[++ tot] = fi[x], to[tot] = y, fi[x] = tot; nt[++ tot] = fi[y], to[tot] = x, fi[y] = tot; } int n, m, x, y; int du[N]; int cur[N], bz[N]; int ans[N][2], ans0; int d[N], d0; void dg(int x, int fr) { for(; cur[x]; ) { int i = cur[x]; cur[x] = nt[cur[x]]; if(bz[i]) continue; bz[i] = bz[i ^ 1] = 1; dg(to[i], i); } if(fr) d[++ d0] = fr; } void work() { int la = 0; fo(i, 1, d0 + 1) { if(i > d0 || d[i] > 2 * m + 1) { for(int j = la + 1; j < i; j += 2) { ans[++ ans0][0] = to[d[j]]; ans[ans0][1] = to[d[j] ^ 1]; } if((i - la) % 2 == 1 && la + 1 < i) { ans[++ ans0][0] = to[d[i - 1]]; ans[ans0][1] = to[d[i - 1] ^ 1]; } la = i; } } } int main() { scanf("%d %d", &n, &m); fo(i, 1, m) { scanf("%d %d", &x, &y); link(x, y); du[x] ++; du[y] ++; } fo(i, 1, n) if(du[i] & 1) { link(n + 1, i); } fo(i, 1, n + 1) { cur[i] = fi[i]; } fo(i, 1, n + 1) { d0 = 0; dg(i, 0); work(); } pp("%d\n", ans0); fo(i ,1, ans0) pp("%d %d\n", ans[i][0], ans[i][1]); }