1. 程式人生 > 其它 >AtCoder Beginner Contest 212 [E - Safety Journey]

AtCoder Beginner Contest 212 [E - Safety Journey]

題意:給定一張無向完全圖,從中打斷幾條邊,問從原點出發經過k步之後能夠回到原點的方案有幾種。

解題思路:看到題第一眼就想到矩陣乘法,火速寫了一發,結果喜提TLE,那麼重新看這道題,題目範圍有5000,因此通過\(n^3\)的矩陣快速冪去求解顯然不現實,那麼重新從DP的角度去看這道題,將\(dp[i][j]\)表示為第i步到達j點的方案數,由於是一張無向完全圖,所到的沒一點都可以由上一次可以到的全部點到達,於是我們可以有此得出遞推方程

\[dp[i+1][j] = \sum_{j'=1} ^ N dp[i][j'] - \sum_{j'∈S_j} dp[i][j'] \]

解題程式碼:

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int maxn = 5000 + 10;
const int mod = 998244353;
vector<int>e[maxn];
int dp[maxn];
int dp2[maxn];
signed main() {
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    int n,m,k,u,v;
	cin >> n >> m >> k;
	for(int i = 0;i < m;i++){
		int u,v;
		cin >> u >> v;
		e[u - 1].push_back(v - 1);
		e[v - 1].push_back(u - 1);
	}
	dp[0] = 1ll;
	for(int i = 1;i <= k;i++){
		int sum = 0;
		for(int j = 0;j < n;j++)sum += dp[j];
		for(int j = 0;j < n;j++){
			dp2[j] = sum - dp[j];
			for(auto t:e[j]) dp2[j] -= dp[t];
			dp2[j] %= mod;
		}
		for(int j = 0;j < n;j++)dp[j] = dp2[j];
	}
	cout << dp[0] << endl;
    return 0;
}