bzoj 1297 [SCOI2009]迷路
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1297
用emacs打的第二道题目!
其实很简单。就是拆点。然后就和poj3613一样了。
把边拆成权值个数的点。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<cstdio> #include<cstring> #define ll long long using namespace std; const int N=1015,mod=2009; int n,tot,T; struct Matrix{ int a[N][N]; Matrix(){memset(a,0,sizeof a);} Matrix operator* (const Matrix &b)const { Matrix c; for(int i=0;i<=tot;i++) for(int k=0;k<=tot;k++) for(int j=0;j<=tot;j++) (c.a[i][j]+=(a[i][k]*b.a[k][j]))%=mod; return c; } }r,ans; int main() { scanf("%d%d",&n,&T);tot=n-1;int x; for(int i=0;i<n;i++) for(int j=0;j<n;j++) { scanf("%1d",&x); if(!x)continue; if(x==1){r.a[i][j]=1;continue;} r.a[i][++tot]=1; for(int k=2;k<x;k++)r.a[tot][++tot]=1; r.a[tot][j]=1; } ans.a[0][0]=1; while(T) { if(T&1)ans=ans*r; r=r*r;T>>=1; } printf("%d\n",ans.a[0][n-1]); return 0; }
但是WA了。可能是数组太大,爆栈了什么的。
其实应该是把点拆成9个点,自己向自己的第一个点走的距离表示连向自己的边的权值。
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int mod=2009,base=9; int n,tot,T; struct Matrix{ int a[95][95]; Matrix(){memset(a,0,sizeof a);} Matrix operator * (const Matrix &b)const { Matrix c; for(int i=1;i<=tot;i++) for(int k=1;k<=tot;k++) for(int j=1;j<=tot;j++) (c.a[i][j]+=a[i][k]*b.a[k][j])%=mod; return c; } }ans,r; int main() { scanf("%d%d",&n,&T);int x;tot=n*base; for(int i=0;i<n;i++) for(int j=0;j<n;j++) { scanf("%1d",&x);if(!x)continue; r.a[i*base+1][j*base+x]=1; } ans.a[1][1]=1; for(int i=tot;i;i--) if((i-2)/base==(i-1)/base) r.a[i][i-1]=1; while(T) { if(T&1)ans=ans*r; r=r*r;T>>=1; } printf("%d\n",ans.a[1][(n-1)*base+1]); return 0; }