您的位置:首页 > 其它

BZOJ1297: [SCOI2009]迷路

2016-01-14 19:22 351 查看
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1297

把每个点拆成9个,然后(x,j)→(x,j-1)。

然后如果存在有一条边x→y,权值为w,(x,1)→(y,w),这样的话跑w次矩阵乘法后它的答案才会被累加到((x,1),(y,1))中。

跑T遍矩阵乘法输出((1,1)(n,1))

#include<cstring>
#include<iostream>
#include<cstdio>
#include<queue>
#include<cmath>
#include<algorithm>
#define rep(i,l,r) for (int i=l;i<=r;i++)
#define down(i,l,r) for (int i=l;i>=r;i--)
#define clr(x,y) memset(x,y,sizeof(x))
#define low(x) (x&(-x))
#define maxn 505
#define inf int(1e9)
#define mm 1000000007
#define ll long long
using namespace std;
int a[105][105],b[105][105],c[105][105];
int n,m,t,x;
char s[105];
int read(){
int x=0,f=1; char ch=getchar();
while (!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
while (isdigit(ch)) {x=x*10+ch-'0'; ch=getchar();}
return x*f;
}
int p(int x,int y){
return (x-1)*9+y;
}
int main(){
n=read(); t=read();
m=n*9;
rep(i,1,n) rep(j,2,9) b[p(i,j)][p(i,j-1)]=1;
rep(i,1,n) {
scanf("%s",s+1); int l=strlen(s+1);
rep(j,1,n) {
x=s[j]-'0';
if (x!=0) b[p(i,1)][p(j,x)]=1;
}
}
rep(i,1,m) a[i][i]=1;
while (t){
if (t&1){
clr(c,0);
rep(i,1,m) rep(j,1,m) rep(k,1,m) c[i][j]=(c[i][j]+a[i][k]*b[k][j])%2009;
rep(i,1,m) rep(j,1,m) a[i][j]=c[i][j];
}
clr(c,0);
rep(i,1,m) rep(j,1,m) rep(k,1,m) c[i][j]=(c[i][j]+b[i][k]*b[k][j])%2009;
rep(i,1,m) rep(j,1,m) b[i][j]=c[i][j];
t/=2;
}
printf("%d\n",a[1][p(n,1)]);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: