题目链接:

闲扯:

这题暴力分似乎挺多,但是一些奇奇怪怪的细节没注意RE了,还是太菜了

分析:

首先我们考虑最naiive的状压DP ,\(f[u][v][state]\)表示u开头,v结尾是否存在一条表示为state的路径,这个好转移不讲了,但是由于d的范围时间复杂度过大,于是考虑折半搜索

我们把一条最终路径的路径分成两部分\(p=(d+1)/2\)(其实就是上取整),\(q=d-p\),显然\(p>=q​\)

于是我们可以把一条路径长度看成两部分,一条从1开始,长度为p的路径,另一条以某点为开头,长度为q,终点恰好与第一条路径接上.

然后这时候我们就用\(ff[state][x]\)表示是否存在一条以x为开头,表示为state的路径,这个DP数组怎么得到呢?

我们枚举起点\(st\),再用一个数组\(f[state][x]\)表示是否存在一条st开头,x结尾,状态为state的路径,这个非常好转移我们从小到达枚举状态再根据两点之间是否连边转移

于是如果\(f[state]\)中存在一个值为1的元素,那么\(ff[state][st]=1\)

由于是折半路径,我们只需要将路径状态压为一个p位二进制数就好了

注意最后路径是从1开始,我们方便起见倒着枚举起点,最后枚举长度为p的前一半状态,和长度为q的后一半状态,如果存在一点v,\(ff[state_1][v]\)&\(f[state_2][v]==1\),那么方案数加1

同时预防前导0还需要特殊处理

还发现DP数组都是0/1序列,使用bitset减少操作时间复杂度

代码:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cctype>
#include <iostream>
#include <bitset>
#define ll long long
#define ri register int
using std::min;
using std::bitset;
using std::max;
template <class T>inline void read(T &x){
x=0;int ne=0;char c;
while(!isdigit(c=getchar()))ne=c=='-';
x=c-48;
while(isdigit(c=getchar()))x=(x<<3)+(x<<1)+c-48;
x=ne?-x:x;return ;
}
const int maxn=95;
const int inf=0x7fffffff;
const int N=1<<20-1;
bitset <maxn> g0[maxn],g1[maxn],f[N],ff[N];
int p,q;
inline void clear(){
for(ri i=0;i<N;i++)f[i].reset();
return ;
}
ll ans=0;
int n,m,d;
int main(){
int x,y,z;
#ifdef Luogu
freopen("y2.in","r",stdin);
freopen("y2.out","w",stdout);
#endif
read(n),read(m),read(d);
int p=(d+1)/2,q=d-p;
int o=1<<p,oo=1<<q;
for(ri i=1;i<=m;i++){
read(x),read(y),read(z);
if(z==1)g1[x][y]=g1[y][x]=1;
else g0[x][y]=g0[y][x]=1;
}
for(ri now=n;now>=1;now--){
clear();
f[1][now]=1;//避免前导0
for(ri i=1;i<o;i++){
for(ri j=1;j<=n;j++){
if(f[i][j]){//now循环中,f[state][v]表示now开头,v结尾状态为state的路径是否存在
f[i<<1]|=g0[j],f[i<<1|1]|=g1[j];
}
}
}//ff[state][u]表示从u开头,是否能走出一条状态为state的路径
for(ri i=0;i<o;i++)ff[i][now]=f[o|i].any();
}
for(ri i=0;i<o;i++){
for(ri j=0;j<oo;j++){
if((ff[i]&f[oo|j]).any())ans++;
}
//若存在点x f[state_1][x]=1并且ff[state_2][x]=1
//说明从x开头能走出一条state_2的路径
//从1开头,x结尾,又能走出一条state_1的路径,这样就能连起来成为一条合法的路径
}
printf("%lld\n",ans);
return 0;
}

最新文章

  1. 使用Ivy管理项目中的依赖
  2. HDU 1846 Brave Game(巴什博弈)
  3. [Cocos2d-x For WP8]Transition 场景切换
  4. 鸟哥笔记:postfix的一些重要配置文件
  5. hdu5548
  6. erlang-string
  7. javascript学习-类型判断
  8. PHP获取指定页面的指定内容
  9. 基于moco的mock server 简单应用 来玩玩吧
  10. pwn-ROP
  11. 穿透dom触发事件
  12. 初学ubuntu命令
  13. C#反射の反射泛型
  14. 「POJ3696」The Luckiest number【数论,欧拉函数】
  15. Kubernetes 选择 IPVS
  16. sublime text 2使用方法
  17. sql server 获取分隔字符串后的长度
  18. MSF渗透测试-CVE-2017-11882(MSOffice漏洞)
  19. ffmpeg h264+ts +udp传输
  20. iOS应用截屏

热门文章

  1. Infralution.Localization.Wpf
  2. Flutter移动电商实战 --(32)列表页_小类高亮交互效果制作
  3. The first one spawns an additional process forwarding requests to a series of workers (think about it as a form of shield, at the same level of apache or nginx), while the second one sets workers to n
  4. Python字符串逐字符或逐词反转方法
  5. 运行React Native项目出现白屏,无法运行
  6. Spring Security(3):配置与自动配置的介绍及源码分析
  7. windows下配置tomcat服务器的jvm内存大小的两种方式
  8. 神经网络手写数字识别numpy实现
  9. Ultimate Guide to Line For Business (May 2019)
  10. SQL FIND_IN_SET() 判断某一个数是否存在于数据表某个以逗号分隔开字段数据中