【BZOJ】1875: [SDOI2009]HH去散步

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1875


 

注意的是路径不可以重复,所以这题把边看成点。每一条无向边拆成两条有向边。

令${F[t][i][j]}$表示从编号为$i$的边走到编号为$j$的边走了$t$步的边集个数。

${F[t][i][j]=\sum f[i-1][i][k]*f[i-1][k][j]}$

这不就是矩乘的形式么,矩乘优化DP即可。


 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<vector>
 5 #include<cstdlib>
 6 #include<cmath>
 7 #include<cstring>
 8 using namespace std;
 9 #define maxn 10010
10 #define llg long long
11 #define SIZE 126
12 #define mod 45989
13 #define yyj(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
14 llg nn,m,A,B,last[maxn*10],t;
15 llg cnt=1;
16 struct MATRIX
17 {
18       llg mt[SIZE][SIZE];
19       llg x,y;
20     void init(){memset(mt,0,sizeof(mt)); x=y=0;}
21 }ans,def;
22 
23 struct edge
24 {
25     llg from,to,next,v;
26 }e[maxn*10];
27 
28 llg in_()
29 {
30     int x=0,f=1;char ch=getchar();
31     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
32     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
33     return x*f;
34 }
35 
36 inline MATRIX operator *(MATRIX a,MATRIX b)
37 {
38     MATRIX c;
39     for (llg i=0;i<=cnt;i++) for (llg j=0;j<=cnt;j++) c.mt[i][j]=0;
40     c.x=a.x; c.y=b.y;
41     for(int i=1;i<=a.x;i++)
42         for(int j=1;j<=b.y;j++)
43             for(int k=1;k<=a.y;k++)
44                 c.mt[i][j]=(c.mt[i][j]+(a.mt[i][k])*(b.mt[k][j]))%mod;
45     return c;
46 }
47 
48 void insert(llg v,llg u)
49 {
50     e[++cnt].to=v; e[cnt].from=u; e[cnt].next=last[u],last[u]=cnt;
51     e[++cnt].to=u; e[cnt].from=v; e[cnt].next=last[v],last[v]=cnt;
52 }
53 
54 int main()
55 {
56     yyj("bzoj1875");
57     cin>>nn>>m>>t>>A>>B;
58     for (llg i=1;i<=m;i++) insert(in_(),in_());
59     MATRIX b;
60     b.init();
61     def.x=def.y=ans.x=ans.y=b.x=b.y=cnt;
62     t--;
63     for (llg i=2;i<=cnt;i++)
64         for (llg j=2;j<=cnt;j++)
65             if (e[i].to==e[j].from && i!=(j^1)) b.mt[i][j]++;
66     for (llg i=1;i<=cnt;i++) ans.mt[i][i]=1;
67     for (llg i=t;i;i>>=1,b=b*b) 
68         if (i&1) 
69             ans=ans*b;
70     for (llg i=last[A];i;i=e[i].next) def.mt[1][i]++;
71     ans=def*ans;
72     llg sum=0;
73     for (llg i=last[B];i;i=e[i].next) sum+=ans.mt[1][i^1];
74     cout<<sum%mod;
75     return 0;
76 }

 

posted @ 2017-02-17 09:42  №〓→龙光←  阅读(197)  评论(2编辑  收藏  举报