P2151 [SDOI2009]HH去散步
Posted Jozky86
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P2151 [SDOI2009]HH去散步相关的知识,希望对你有一定的参考价值。
题意:
HH有个一成不变的习惯,喜欢饭后百步走。所谓百步走,就是散步,就是在一定的时间 内,走过一定的距离。 但是同时HH又是个喜欢变化的人,所以他不会立刻沿着刚刚走来的路走回。 又因为HH是个喜欢变化的人,所以他每天走过的路径都不完全一样,他想知道他究竟有多 少种散步的方法。
现在给你学校的地图(假设每条路的长度都是一样的都是1),问长度为t,从给定地 点A走到给定地点B共有多少条符合条件的路径
题解:
这题跟裸的矩阵快速幂唯一区别是,本题中不允许刚经过的边,本题中给的是无向边,顿时没有什么思路。
我们可以点边互换,将边成是点,然后再重新建边,如果原图中有4个边,分别编号1~4,然后我们依次判断第i个边的尾和第j个边的头是否连接,如果连接就从第i个边向第j个边连一条边,
如何处理走回去的情况,只要我们同一条边拆出来的两个点互不连边即可
代码:
// Problem: P2151 [SDOI2009]HH去散步
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P2151
// Memory Limit: 125 MB
// Time Limit: 1000 ms
// Data:2021-08-13 16:47:00
// By Jozky
#include <bits/stdc++.h>
#include <unordered_map>
#define debug(a, b) printf("%s = %d\\n", a, b);
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
clock_t startTime, endTime;
//Fe~Jozky
const ll INF_ll= 1e18;
const int INF_int= 0x3f3f3f3f;
template <typename T> inline void read(T& x)
{
T f= 1;
x= 0;
char ch= getchar();
while (0 == isdigit(ch)) {
if (ch == '-')
f= -1;
ch= getchar();
}
while (0 != isdigit(ch))
x= (x << 1) + (x << 3) + ch - '0', ch= getchar();
x*= f;
}
template <typename T> inline void write(T x)
{
if (x < 0) {
x= ~(x - 1);
putchar('-');
}
if (x > 9)
write(x / 10);
putchar(x % 10 + '0');
}
const int maxn= 151, mod= 45989;
int n, m, s, t, x[maxn], y[maxn], cnt;
ll T;
struct Ma
{
ll m[maxn][maxn];
};
Ma mul(Ma a, Ma b, int n)
{
Ma temp;
memset(&temp, 0, sizeof(temp));
for (int i= 1; i <= n; i++) {
for (int j= 1; j <= n; j++) {
for (int k= 1; k <= n; k++) {
temp.m[i][j]= (temp.m[i][j] + ((a.m[i][k] % mod) * (b.m[k][j]) % mod) % mod) % mod;
}
}
}
return temp;
}
Ma poww(Ma res, ll N, int n)
{
Ma ans;
for (int i= 1; i <= n; i++) {
ans.m[i][i]= 1;
}
while (N) {
if (N & 1)
ans= mul(ans, res, n);
res= mul(res, res, n);
N>>= 1;
}
return ans;
}
Ma A;
void add(int u, int v)
{
x[++cnt]= u;
y[cnt]= v;
}
int main()
{
//rd_test();
scanf("%d%d%lld%d%d", &n, &m, &T, &s, &t);
s++;
t++;
x[++cnt]= 0;
y[cnt]= s;
for (int i= 1, u, v; i <= m; i++) {
scanf("%d%d", &u, &v);
u++, v++;
x[++cnt]= u, y[cnt]= v;
x[++cnt]= v, y[cnt]= u;
}
for (int i= 1; i <= cnt; i++)
for (int j= 1; j <= cnt; j++)
if (i != j && i != (j ^ 1)) {
if (y[i] == x[j])
A.m[i][j]= 1;
}
Ma Ans= poww(A, T, cnt);
int ans= 0;
for (int i= 1; i <= cnt; i++)
if (y[i] == t) {
ans= (ans + Ans.m[1][i]) % mod;
}
cout << ans << endl;
return 0;
//Time_test();
}
以上是关于P2151 [SDOI2009]HH去散步的主要内容,如果未能解决你的问题,请参考以下文章