思路:矩乘优化DP

提交:3次(用了一个奇怪的东西导致常数过大)

题解:

如果可以走完正向边后又走反向边那就显然了,但是不能走,所以我们要将正反向边分别编号,区分正反向边。

所以这道题的矩阵是以边的编号(边的邻接矩阵),而非点来DP的。

具体地,记录每个边$w_i=(u_i,v_i)$和$w_{i^1}=(v_{i^1},u_{i^1})$,注意这个有向的。

设起点为$s$,终点为$t$,我们的初始矩阵$S$是一根行向量,把所有的$w_i \ and \ u_i==s $设为$1$,表示$s$与$w_i$连通;

然后转移矩阵$a$:若$v_i==u_j \ and \ i!=j \ xor \ 1$ ,即两条边相连,但不是互为正反向边,则在边的邻接矩阵中设为$1$。

然后快速幂,并令$ans=S*a$

最后求解答案时,统计所有$ans$中$w_i \ and \ v_i==t$ 的答案,即为最终的答案。

代码:

#include<cstdio>
#include<iostream>
#include<cstring>
#define R register int
using namespace std;
//你弱,有什么资格休息
#define ull unsigned long long
#define ll long long
#define pause (for(R i=1;i<=10000000000;++i))
#define In freopen("NOIPAK++.in","r",stdin)
#define Out freopen("out.out","w",stdout)
namespace Fread {
static char B[<<],*S=B,*D=B;
#ifndef JACK
#define getchar() (S==D&&(D=(S=B)+fread(B,1,1<<15,stdin),S==D)?EOF:*S++)
#endif
inline int g() {
R ret=,fix=; register char ch; while(!isdigit(ch=getchar())) fix=ch=='-'?-:fix;
if(ch==EOF) return EOF; do ret=ret*+(ch^); while(isdigit(ch=getchar())); return ret*fix;
} inline bool isempty(const char& ch) {return (ch<=||ch>=);}
inline void gs(char* s) {
register char ch; while(isempty(ch=getchar()));
do *s++=ch; while(!isempty(ch=getchar()));
}
} using Fread::g; using Fread::gs; namespace Luitaryi {
const int N=,M=;
int n,m,p,S,T,cnt=-,x[N],y[N];
int a[N][N],s[][N],ans[][N],anss;
inline void mul(int a[][N],int b[][N]) { R tmp[N][N]; memset(tmp,,sizeof(tmp));
for(R i=;i<=cnt;++i) for(R k=;k<=cnt;++k) for(R j=;j<=cnt;++j)
(tmp[i][j]+=1ll*a[i][k]*b[k][j]%M)%=M;
memcpy(a,tmp,sizeof(tmp));
}
inline void qpow(int p) {
R ret[N][N]; memset(ret,,sizeof(ret));
for(R i=;i<=cnt;++i) ret[i][i]=;
for(;p;p>>=,mul(a,a)) if(p&) mul(ret,a);
memcpy(a,ret,sizeof(ret));
}
inline void main() {
n=g(),m=g(),p=g(),S=g(),T=g();
for(R i=;i<=m;++i) {
R u=g(),v=g();
x[++cnt]=u,y[cnt]=v;
x[++cnt]=v,y[cnt]=u;
} for(R i=;i<=cnt;++i) for(R j=;j<=cnt;++j) if(i!=(j^)&&y[i]==x[j]) a[i][j]+=;
for(R i=;i<=cnt;++i) if(x[i]==S) s[][i]=;
qpow(p-); for(R i=;i<=cnt;++i) for(R j=;j<=cnt;++j) (ans[][j]+=1ll*s[][i]*a[i][j]%M)%=M;
for(R i=;i<=cnt;++i) if(y[i]==T) (anss+=ans[][i])%=M; printf("%d\n",anss);
}
}
signed main() {
Luitaryi::main();
}

2019.07.20

最新文章

  1. Shell入门教程:Shell的基本结构
  2. 【转】Weblogic的集群
  3. eclipse 编译android程序 编译错误
  4. 在网上看到的一篇文章关于js和php编码的
  5. awk处理之案例一:awk 处理百分比的问题
  6. 作业调度框架 Quartz.NET 2.0 StepByStep
  7. iOS 8创建交互式通知-备
  8. Java琐碎知识点
  9. ASP.NET Web API中使用OData
  10. 基础总结篇之五:BroadcastReceiver应用具体解释
  11. 201521123020《java程序设计》 第11周学习总结
  12. Codeforces Round #301 (Div. 2)(A,【模拟】B,【贪心构造】C,【DFS】)
  13. Javascript中获取浏览器类型和操作系统版本等客户端信息常用代码
  14. 轻松搞懂elasticsearch概念
  15. visio连接线设置
  16. [Android App]IFCTT,即:If Copy Then That,一个基于IFTTT的&quot;This&quot;实现
  17. Java如何与Web服务器连接?
  18. 自动化测试-20.selenium之FireFox下载项配置
  19. 虚拟机中安装CentOS7
  20. tomcat设置开机自启动和后台运行

热门文章

  1. Python之对象持久化笔记
  2. 【C#】课堂知识点#1
  3. SAS学习笔记27 卡方检验
  4. Redis过期命令
  5. cocos发布遇到的问题
  6. 【Redis】事务 (超详细)
  7. linux 基础10-磁盘配额管理
  8. 网络OSI 7层模型
  9. opengl 4.5 中文api 链接
  10. [Python] Codecombat 攻略 Sarven 沙漠 (1-43关)截止至36关