【2018-国庆雅礼-NOIP-培训】-D4T2-y 发表于 2018-10-04 题解看到数据范围后便知道搜索必定爆炸,那就只好用动规了 $f[i][j][mask]$ 表示从 $i$ 出发,$j$ 结束,是否存在一条表示为 $mask$ 的路径。 但我们发现还是会超时。 于是我们进行二分(果然二分超级实用的说)————对于每种可能的路径,枚举中间的那个位置判断。时间复杂度为 $O(2^{\frac d 2} ∗n∗(n + m) + 2^d ∗n)$ 来一发bitset可以整体除以 64,可以把 n 开得更大 标程123456789101112131415161718192021222324252627282930313233343536373839#include<bits/stdc++.h>using namespace std;const int maxn=90+10,maxmask=1<<20/2+1;int n,m,d,d1,d2,ans;bitset<maxn> g0[maxn],g1[maxn],dp[maxmask],f[maxmask];int main(){ freopen("y.in","r",stdin); freopen("y.out","w",stdout); scanf("%d%d%d",&n,&m,&d); for(int i=1,u,v,c;i<=m;++i){ scanf("%d%d%d",&u,&v,&c); if(c) g1[u][v]=g1[v][u]=true; else g0[u][v]=g0[v][u]=true; } d2=d/2;d1=d-d2; for(int u=n;u;--u){ for(int i=0;i<maxmask;++i) dp[i].reset(); dp[1][u]=true; for(int x=1;x<1<<d1;++x) for(int v=1;v<=n;++v) if(dp[x][v]){ dp[x<<1]|=g0[v]; dp[x<<1|1]|=g1[v]; } for(int x=0;x<1<<d1;++x) f[x][u]=dp[1<<d1|x].any(); } for(int i=0;i<1<<d1;++i) for(int j=0;j<1<<d2;++j) if((dp[1<<d2|j]&f[i]).any()) ++ans; printf("%d\n",ans); return 0;}