[SDOI2009]
- 就是求从S到T有多少条长度为t的路径,满足当前走过的路不能是上一次走过的
40pts
- 无脑爆搜?
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
using namespace std;
const int mod=45989;
const int N=1e5;
struct node{int y,n;}e[N];
int lin[N],v[N],len=1,ans=0,n,m,t,x,y,a,b;
void read(int x,int y)
{e[++len].y=y,e[len].n=lin[x],lin[x]=len;}
void dfs(int x,int d,int pre){
if(d>t)return;
if(x==b&&d==t){
ans++;
if(ans>=mod)ans-=mod;
return;
}
for(int i=lin[x];i;i=e[i].n){
int y=e[i].y;
if((i^1)==pre)continue;
dfs(y,d+1,i);
}
}
int main()
{
scanf("%d%d%d%d%d",&n,&m,&t,&a,&b);
rep(i,1,m){
scanf("%d%d",&x,&y);
read(x,y),read(y,x);
}
dfs(a,0,0);
cout<<ans;
return 0;
}
- 动态规划
- f[i][j]表示目前已经走了i步,上一次走过的边是j的方案数
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
using namespace std;
const int mod=45989;
const int N=1e6;
struct node{int y,n;}e[N];
int lin[N],len=1,ans=0,n,m,t,x,y,a,b;
void read(int x,int y)
{e[++len].y=y,e[len].n=lin[x],lin[x]=len;}
map<int,map<int,int> > f;
int main()
{
scanf("%d%d%d%d%d",&n,&m,&t,&a,&b);
rep(i,1,m){
scanf("%d%d",&x,&y);
read(x,y),read(y,x);
}
for(int i=lin[a];i;i=e[i].n)f[1][i]=1;
rep(i,1,t){
rep(j,2,len){
if(e[j].y==b&&i==t)ans=(ans+f[i][j])%mod;
for(int k=lin[e[j].y];k;k=e[k].n){
int y=e[k].y;
if((k^1)!=j)
f[i+1][k]=(f[i+1][k]+f[i][j])%mod;
}
}
}
cout<<ans;
return 0;
}
100pts
- 考虑动态规划的转移可以用矩阵乘法优化,构造一个合法的转移矩阵每次矩阵快速幂即可
- 本地运行的时候爆栈了,手动开栈
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
using namespace std;
const int mod=45989;
const int N=300;
struct node{int y,n;}E[N];
struct mat{int m[N][N];};
int lin[N],len=0,ans=0,n,m,t,x,y,s,ed;
mat a,b,e;
void read(int x,int y)
{E[++len].y=y,E[len].n=lin[x],lin[x]=len;}
int o(int x){return ((x%2)?(x+1):(x-1));}
mat mul(mat x,mat y)
{
mat c;rep(i,1,len)rep(j,1,len)c.m[i][j]=0;
rep(i,1,len)rep(j,1,len)rep(k,1,len)
c.m[i][j]=(c.m[i][j]+x.m[i][k]*y.m[k][j]%mod)%mod;
return c;
}
mat pow(mat x,int y){mat ans=e;for(;y;y>>=1,x=mul(x,x))if(y&1)ans=mul(ans,x);return ans;}
int main()
{
scanf("%d%d%d%d%d",&n,&m,&t,&s,&ed);
rep(i,1,m){
scanf("%d%d",&x,&y);
read(x,y),read(y,x);
}
for(int i=lin[s];i;i=E[i].n)a.m[1][i]=1;
rep(i,1,len){
for(int j=lin[E[i].y];j;j=E[j].n){
if(i==o(j))continue;
b.m[i][j]=1;
}
}
rep(i,1,len)e.m[i][i]=1;
b=pow(b,t-1);
a=mul(a,b);
rep(i,1,len)if(E[i].y==ed)ans=(ans+a.m[1][i])%mod;
cout<<ans;
return 0;
}