[HDU2157]How many ways??(DP + 矩阵优化)

Posted 蒟蒻zht的博客

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[HDU2157]How many ways??(DP + 矩阵优化)相关的知识,希望对你有一定的参考价值。

传送门

 

k < 20

k这么小,随便dp一下就好了。。。

dp[i][j][k]表示从i到j经过k个点的方案数

4重循环。。

 

但是如果k很大就不好弄了

把给定的图转为邻接矩阵,即A(i,j)=1当且仅当存在一条边i->j。令C=A*A,那么C(i,j)=ΣA(i,k)*A(k,j),实际上就等于从点i到点j恰好经过1个点的路径数(枚举k为中转点)。类似地,C*A的第i行第j列就表示从i到j经过2个点的路径数。同理,如果要求经过k步的路径数,我们只需要二分求出A^k即可。

 

#include <cstdio>
#include <cstring>
#define p 1000

int n, m, k, T;

struct Matrix
{
	int n, m;
	int a[21][21];
	Matrix()
	{
		n = m = 0;
		memset(a, 0, sizeof(a));
	}
}ans;

inline Matrix operator * (Matrix x, Matrix y)
{
	int i, j, k;
	Matrix ans;
	ans.n = x.n;
	ans.m = y.m;
	for(i = 1; i <= x.n; i++)
		for(j = 1; j <= y.m; j++)
			for(k = 1; k <= y.n; k++)
				ans.a[i][j] = (ans.a[i][j] + x.a[i][k] * y.a[k][j]) % p;
	return ans;
}

inline Matrix operator ^ (Matrix x, int y)
{
	int i;
	Matrix ans;
	ans.n = ans.m = n;
	for(i = 1; i <= n; i++) ans.a[i][i] = 1;
	for(; y; y >>= 1)
	{
		if(y & 1) ans = x * ans;
		x = x * x;
	}
	return ans;
}

int main()
{
	int i, x, y;
	while(~scanf("%d %d", &n, &m) && n + m)
	{
		Matrix c;
		c.n = c.m = n;
		for(i = 1; i <= m; i++)
		{
			scanf("%d %d", &x, &y);
			c.a[x + 1][y + 1] = 1;
		}
		scanf("%d", &T);
		for(i = 1; i <= T; i++)
		{
			scanf("%d %d %d", &x, &y, &k);
			ans = c ^ k;
			printf("%d\n", ans.a[x + 1][y + 1]);
		}
	}
	return 0;
}

  

以上是关于[HDU2157]How many ways??(DP + 矩阵优化)的主要内容,如果未能解决你的问题,请参考以下文章

HDU2157 How many ways??---(邻接矩阵,图论,矩阵快速幂)

HDU 2157 How many ways??

hdu2157:How many ways??

hdu 2157 How many ways?? (可达矩阵)

HDU2157 How many ways矩阵再识

HDU 2157 How many ways?矩阵快速幂