[BZOJ] 1875: [SDOI2009]HH去散步
题意:给出一个无向图,求s到t经过k条路的方案数,且不能存在从A到B再到A这样的路径
用Floyd类型的矩阵乘法,不同的是这里的邻接矩阵是对于边的,这样就能防止走回来了
#include<iostream> #include<cstring> #include<cstdio> using namespace std; const int MAXN=64<<2; const int MOD=45989; struct Edge{ int next,to,from; }e[MAXN<<1]; int ecnt=1,head[MAXN]; inline void add(int x,int y){ e[++ecnt]={head[x],y,x}; head[x]=ecnt; } struct Mat{ int data[MAXN][MAXN]; Mat(){memset(data,0,sizeof(data));} Mat operator*(const Mat &rhs){ Mat ret; for(int k=2;k<=ecnt;k++) for(int i=2;i<=ecnt;i++) for(int j=2;j<=ecnt;j++) ret.data[i][j]=(ret.data[i][j]+data[i][k]*rhs.data[k][j])%MOD; return ret; } Mat operator^(int x){ Mat ret;for(int i=2;i<=ecnt;i++)ret.data[i][i]=1; for(Mat base=*this;x;x>>=1){ if(x&1) ret=ret*base; base=base*base; } return ret; } }; int n,m,k,s,t; int mp[MAXN][MAXN]; int main(){ cin>>n>>m>>k>>s>>t; int x,y;s++;t++; for(int i=1;i<=m;i++){ cin>>x>>y;x++;y++; add(x,y);add(y,x); } for(int i=2;i<=ecnt;i++){ for(int j=2;j<=ecnt;j++){ if(e[i].to==e[j].from&&(i!=(j^1))) mp[i][j]=1; } } Mat T,S; memcpy(T.data,mp,sizeof(mp)); T=T^(k-1); for(int i=head[s];i;i=e[i].next){ S.data[2][i]++; } S=S*T; int ans=0; for(int i=head[t];i;i=e[i].next){ int v=i^1; ans+=S.data[2][v];ans%=MOD; } cout<<ans<<endl; return 0; }
本文来自博客园,作者:GhostCai,转载请注明原文链接:https://www.cnblogs.com/ghostcai/p/9363204.html