CF 1425B Blue and Red of Our Faculty!
阿新 • • 發佈:2021-01-20
- 給出 \(m\) 個環,它們兩兩之間有且僅有一個交點 \(1\),求出有多少種選擇出 兩條起點為 \(1\) 長度相同的路徑分別記為 \(Red,Blue\),且邊沒有重複,並且不能夠再拓展 的方案數,兩種方案不同當且僅當至少對應的 \(Red,Blue\) 中至少有一個選取邊的集合不同,保證環長度的總和小於 \(4000\)。
顯然最後結束時兩人相距不超過 \(1\),否則它們均可以再走一步。
每人走的路徑集合必定有若干個完整的環,可以再接一段殘缺的環。
那麼考慮按照最終的位置分別統計。
在 \(1\) 處相遇,那麼就是將所有環劃分為兩個不同集合,求每個集合的環長度之和相等。
均走進了同一個環,且相距為 \(0/1\)
只有 \(1\) 人走進環並且距離,另外一人在 \(1\) 處,相距為 \(1\),那麼就是選出一個環的長度減 \(1\),剩下的由兩人分完,總和相同的方案數。
都可以用類似於揹包的方法搞。
#include <bits/stdc++.h> #define rep(i, a, b) for (int i = (a); i <= (b); i++) #define per(i, a, b) for (int i = (a); i >= (b); i--) #define fi first #define se second using namespace std; typedef long long LL; typedef pair <int, int> P; const int inf = 0x3f3f3f3f, N = 2005, mod = 1e9 + 7; template <typename T> void rd_(T &x) { x = 0; int f = 1; char ch = getchar(); for (; ch > '9' || ch < '0'; ch = getchar()) if (ch == '-') f = -1; for (; ch >= '0' && ch <= '9'; ch = getchar()) x = x*10 + ch - '0';x *= f; } vector <int> h[N]; int n, m, s[N], tot, f[2][N<<2][2], cur, g[2][N<<2], ans; bool vis[N]; void dfs_(int u) { vis[u] = 1, s[tot]++; for (int v, i = 0; i < (int) h[u].size(); i++) { v = h[u][i]; if (vis[v]) continue; dfs_(v); } } int main() { rd_(n), rd_(m); for (int u, v, i = 1; i <= m; i++) { rd_(u), rd_(v); h[u].push_back(v), h[v].push_back(u); } vis[1] = 1; rep (i, 0, (int) h[1].size() - 1) { int u = h[1][i]; if (!vis[u]) { s[++tot] = 1; dfs_(u); } } f[0][m][0] = 1; rep (i, 1, tot) { cur ^= 1; rep (j, 0, 2*m) { f[cur][j][0] = f[cur^1][j][0]; f[cur][j][1] = f[cur^1][j][1]; if (j >= s[i]) { f[cur][j][0] = (f[cur][j][0] + f[cur^1][j - s[i]][0])%mod; f[cur][j][1] = (f[cur][j][1] + f[cur^1][j - s[i]][1])%mod; } if (j + s[i] <= 2*m) { f[cur][j][0] = (f[cur][j][0] + f[cur^1][j + s[i]][0])%mod; f[cur][j][1] = (f[cur][j][1] + f[cur^1][j + s[i]][1])%mod; } rep (k, 1, s[i] - 1) { int d = 2*k - s[i]; if (j >= d) f[cur][j][1] = (f[cur][j][1] + f[cur^1][j - d][0]*2ll)%mod; } rep (k, 1, s[i] - 2) { int d = 2*k - s[i] + 1; if (j >= d) f[cur][j][1] = (f[cur][j][1] + f[cur^1][j - d][0]*2ll)%mod; } } } ans = f[cur][m][1]; g[cur = 0][m] = 1; rep (i, 1, tot) { cur ^= 1; rep (j, 0, 2*m) { g[cur][j] = 0; if (j >= s[i]) g[cur][j] = (g[cur][j] + g[cur^1][j - s[i]])%mod; if (j + s[i] <= 2*m) g[cur][j] = (g[cur][j] + g[cur^1][j + s[i]])%mod; } } ans = (ans + g[cur][m])%mod; memset(f, 0, sizeof(f)); f[cur = 0][m][0] = 1; rep (i, 1, tot) { cur ^= 1; rep (j, 0, 2*m) { f[cur][j][0] = 0; f[cur][j][1] = 0; if (j >= s[i]) { f[cur][j][0] = (f[cur][j][0] + f[cur^1][j - s[i]][0])%mod; f[cur][j][1] = (f[cur][j][1] + f[cur^1][j - s[i]][1])%mod; } if (j + s[i] <= 2*m) { f[cur][j][0] = (f[cur][j][0] + f[cur^1][j + s[i]][0])%mod; f[cur][j][1] = (f[cur][j][1] + f[cur^1][j + s[i]][1])%mod; } if (j + s[i] - 1 <= 2*m) f[cur][j][1] = (f[cur][j][1] + f[cur^1][j + s[i] - 1][0]*2ll)%mod; if (j - (s[i] - 1) >= 0) f[cur][j][1] = (f[cur][j][1] + f[cur^1][j - s[i] + 1][0]*2ll)%mod; } } ans = (ans + f[cur][m][1])%mod; printf("%d\n", ans); }