[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;
}

 

posted @ 2018-07-24 22:54  GhostCai  阅读(117)  评论(0编辑  收藏  举报