一個很好的在圖上的dp
阿新 • • 發佈:2022-03-21
ABC244 E - King Bombee
題目連結
https://atcoder.jp/contests/abc244/tasks/abc244_e
解析
本題就是給了一個無向無環圖,然後問你從s到t經過k條路徑的方案數,要求經過的路徑中x只出現了偶數次.採用dp的做法.
- 如果不考慮x出現偶數次,則dp方法與該題相同:
https://atcoder.jp/contests/abc242/tasks/abc242_c
用f[i][j]表示從起點到j經過i條邊的方案數. - 考慮x出現次數的奇偶,則應增加一維狀態表示(像是狀態壓縮dp)
- f[i][j][0]表示從起點到j經過i條邊且有偶數個x的方案數
- f[i][j][1]表示從起點到j經過i條邊且有奇數個x的方案數
- 狀態轉移是通過圖中的邊來轉移的
- 官方題解寫的很好,直接參考即可
https://atcoder.jp/contests/abc244/editorial/3619
Ac程式碼
點選檢視程式碼
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; const int mod = 998244353; const int N = 2010, M = 2 * N; int h[N], e[M], ne[M], idx; int n, m, k, s, t, x; ll f[N][N][2]; void add(int a, int b){ e[idx] = b, ne[idx] = h[a], h[a] = idx ++; } int main() { scanf("%d%d%d%d%d%d", &n, &m, &k, &s, &t, &x); memset(h, -1, sizeof h); while(m --){ int a, b; scanf("%d%d", &a, &b); add(a, b), add(b, a); } f[0][s][0] = 1; for(int i = 1; i <= k; i ++){ for(int j = 1; j <= n; j ++){ for(int k = h[j]; k != -1; k = ne[k]){ int tmp = e[k]; if(tmp == x){ f[i][tmp][1] = (f[i][tmp][1] + f[i - 1][j][0]) % mod; f[i][tmp][0] = (f[i][tmp][0] + f[i - 1][j][1]) % mod; } else{ f[i][tmp][1] = (f[i][tmp][1] + f[i - 1][j][1]) % mod; f[i][tmp][0] = (f[i][tmp][0] + f[i - 1][j][0]) % mod; } } } } printf("%lld\n", f[k][t][0]); return 0; }