給定 \(n\) 個點 \(m\) 條邊的簡單有向圖,每條邊上有一個長度 \(\le n\) 的頂點序列,\(\forall i\in[1,2n]\) 求將邊的頂點序列相接獲得該路徑的長度爲 \(i\) 的路徑個數\(\bmod(10^9+7)\)。c++
\(n\le 50\)。ide
首先,一個符合條件的路徑一定有一條邊 \((x,y)\) 的頂點序列包含連續的 \(x,y\),因而咱們能夠從這條邊向左右擴展出一條合法路徑。spa
可是這題要求數數,咱們要不重不漏地考慮全部的合法路徑。code
能夠向前補一條缺結尾的路徑,或者向後補一條缺開頭的路徑,或者把兩條合法路徑通過一條空邊連起來。get
這個過程能夠看作將四種路徑 \((0/1,0/1)\) 拼接起來,分別表示缺/不缺開頭/結尾,均可以用相似的擴展方法預處理出來,作個揹包就能夠求出答案。it
時間複雜度 \(O(n^2m)\)。class
#include<bits/stdc++.h> #define PB emplace_back using namespace std; const int N = 53, M = N*N, mod = 1e9+7; template<typename T> void rd(T &x){ int ch = getchar(); x = 0; for(;ch < '0' || ch > '9';ch = getchar()); for(;ch >= '0' && ch <= '9';ch = getchar()) x = x * 10 + ch - '0'; } void qmo(int &x){x += x >> 31 & mod;} int n, m, id[N][N], x[M], y[M], l[M], q[N<<1], fr, re, dp[N<<1][N][2]; vector<int> a[M]; struct Node { int to, l; bool st, ed; Node(int _a = 0, int _b = 0, bool _c = 0, bool _d = 0): to(_a), l(_b), st(_c), ed(_d){} }; vector<Node> pt[N]; int main(){ rd(n); rd(m); for(int i = 1;i <= m;++ i){ rd(x[i]); rd(y[i]); rd(l[i]); a[i].resize(l[i]); id[x[i]][y[i]] = i; for(int j = 0;j < l[i];++ j) rd(a[i][j]); } for(int i = 1, p, e;i <= m;++ i){ for(p = 0;p+1 < l[i];++ p) if(a[i][p] == x[i] && a[i][p+1] == y[i]) break; if(!l[i]) pt[x[i]].PB(y[i], 1, 0, 0); else if(p+1 < l[i]){ q[re = 0] = x[i]; for(int j = p-1;~j;-- j) q[++re] = a[i][j]; for(fr = 0;fr < re && (e = id[q[fr+1]][q[fr]]) && re <= (n<<1);++ fr) for(int j = l[e]-1;~j && re <= (n<<1);-- j) q[++re] = a[e][j]; if(fr < re) continue; int St = q[re], Le = re+1; q[re = 0] = y[i]; for(int j = p+2;j < l[i];++ j) q[++re] = a[i][j]; for(fr = 0;fr < re && (e = id[q[fr]][q[fr+1]]) && re <= (n<<1);++ fr) for(int j = 0;j < l[e] && re <= (n<<1);++ j) q[++re] = a[e][j]; if(fr == re) pt[St].PB(q[re], Le+re, 1, 1); } else if(a[i][0] == y[i]){ q[re = 0] = y[i]; for(int j = 1;j < l[i];++ j) q[++re] = a[i][j]; for(fr = 0;fr < re && (e = id[q[fr]][q[fr+1]]) && re <= (n<<1);++ fr) for(int j = 0;j < l[e] && re <= (n<<1);++ j) q[++re] = a[e][j]; if(fr == re) pt[x[i]].PB(q[re], re+1, 0, 1); } else if(a[i][l[i]-1] == x[i]){ q[re = 0] = x[i]; for(int j = l[i]-2;~j;-- j) q[++re] = a[i][j]; for(fr = 0;fr < re && (e = id[q[fr+1]][q[fr]]) && re <= (n<<1);++ fr) for(int j = l[e]-1;~j && re <= (n<<1);-- j) q[++re] = a[e][j]; if(fr == re) pt[q[re]].PB(y[i], re+1, 1, 0); } } for(int i = 1;i <= n;++ i) dp[0][i][0] = 1; for(int i = 0;i < (n<<1);++ i) for(int j = 1;j <= n;++ j) for(Node _ : pt[j]) if(i+_.l <= (n<<1)) qmo(dp[i+_.l][_.to][_.ed] += dp[i][j][!_.st] - mod); for(int i = 1;i <= (n<<1);++ i){ int ans = 0; for(int j = 1;j <= n;++ j) qmo(ans += dp[i][j][1] - mod); printf("%d\n", ans); } }