题意介绍
n个点的强连通图(每个点之间都相互连接,有(n-1)*n/2个),但是现在有m条边被损坏,不能走了,现在问从1开始走经过k-1个点,再次到达终点1的路径数,不可以原地踏步.路径一共K+1个点,起点和终点都是1,中间点随意。答案要对 998244353取模 (n<= 5000 k <= 5000)
思路:
最开始没有往dp上想, 可能是近段时间没做过dp,仔细一看原来是个简单的计数dp问题
根据y总dp分析 状态表示:f[i][j]表示走到i号点经过了j步的方案数 状态计算: 可知f[i][j] = f[1–N][j - 1]的总和
其中又包含了上一个点也是自己的情况和当前路不通的情况 , 再给他们相减就可以了 时间复杂度大概为O(N * K)
除此之外 可以发现 使用邻接表存图和链式前向星存图大致是一样的
但是 邻接表可以直接得知与当前点相连有几条边且操纵简单,且也可以直接对与当前点相连的点直接使用sort等
但是 遇到大的图论问题 还是要用链式前向星
其中切记: 凡是出现了减号 取模问题 一定要在后面加上 mod 再取模
f[j][i] = (sum - f[j][i - 1] + mod) % mod;
f[j][i] = (f[j][i] - f[alls[j][c]][i - 1] + mod ) % mod;
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <unordered_map>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int maxn = 5010 + 10;
typedef pair <int, int> PII;
vector <int> alls[maxn];
int f[5010][5010];
const int mod = 998244353;
int main()
{
int N , M ,K;
scanf("%d %d %d", &N, &M, &K);
for(int i = 1 ; i <= M ; i ++)
{
int u, v;
scanf("%d %d", &u, &v);
alls[u].push_back(v);
alls[v].push_back(u);
}
f[1][0] = 1;
for(int i = 1 ; i <= K ; i ++)
{
int sum = 0;
for(int j = 1 ; j <= N ; j ++)
sum = (sum + f[j][i - 1]) % mod;
for(int j = 1 ; j <= N ; j ++)
{
f[j][i] = (sum - f[j][i - 1] + mod) % mod;
for(int c = 0 ; c < alls[j].size() ; c ++)
{
f[j][i] = (f[j][i] - f[alls[j][c]][i - 1] + mod ) % mod;
}
}
}
printf("%d\n", f[1][K] % mod);
return 0;
}