【HDU2157】有向图邻接矩阵应用

1.题目链接。题目大意:给定一个有向图,从图中一点a到另一点b只走k步(包括b)有多少种方案?

2.这是一个很有用的性质,结论就是这个图邻接矩阵的k次幂对应的矩阵那个点的数值。其实证明也不难,我们从矩阵乘法可以看出一点端倪:c[i][j]=c[i][j]+a[i][k]*b[k][j].这个k就是位于i和j之间的点,枚举k,求和就是方案数。这个性质我忘了叫做什么了,只是在学习离散的时候听老师讲了一下,当时觉得还是比较有用的,就记了下来。代码如下:

#include<bits/stdc++.h>
#include<string>
using namespace std;
#pragma warning(disable:4996)

struct Sarray
{
	static const int LEN = 25;
	static const int mod = 1000;
	int len, data[LEN][LEN];

	Sarray(int len, int flag) :len(len) {
		for (int i = 0; i < len; i++) {
			for (int j = 0; j < len; j++)data[i][j] = 0;
			data[i][i] = flag;
		}
	}
	Sarray() {};
	Sarray operator *(const Sarray&a) {
		Sarray tem(a.len, 0);
		for (int i = 0; i < len; i++) {
			for (int j = 0; j < len; j++) {
				for (int k = 0; k < len; k++) {
					tem.data[i][j] = (tem.data[i][j] + data[i][k] * a.data[k][j]) % mod;
				}
			}
		}
		return tem;
	}

	Sarray operator +(const Sarray&a)
	{
		Sarray tem(a.len, 0);
		for (int i = 0; i < len; i++) {
			for (int j = 0; j < len; j++) {
				tem.data[i][j] = (data[i][j] + a.data[i][j]) % mod;
			}
		}
		return tem;
	}

};

Sarray qpow(Sarray a, int b)
{
	Sarray tem(a.len, 1);
	while (b) {
		if (b & 1)tem = a * tem;
		a = a * a;
		b >>= 1;
	}
	return tem;
}
Sarray g(25, 0);
int main()
{
	int n, m;
	while (~scanf("%d%d", &n, &m) && (n + m))
	{
		memset(g.data, 0, sizeof(g.data));
		for (int i = 0; i < m; i++)
		{
			int u, v;
			scanf("%d%d", &u, &v);
			g.data[u][v] = 1;

		}
		int T;
		scanf("%d", &T);
		while (T--)
		{
			int a, b, k;
			scanf("%d%d%d", &a, &b, &k);
			Sarray c = qpow(g, k);
			cout << c.data[a][b] << endl;
		}
	}
}

最后需要说明的是:在我们if判断的时候,千万不要写成while(~scanf("%d%d",&n,&m)&&n&&m).为什么呢,因为这里m是可以为0的,m为0的时候就是在说这个图中没有任何的边的存在,这个图也是合法的,所以这样判断输入结束是错误的。

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值