【SSLOJ1471】Y

题目

思路

\(f[i][j][s]\) 表示 \(i\)\(j\) 之间是否存在状态为 \(s\) 的路径。时间复杂度 \(O(2^n\times n^2)\)
显然这并不是一个可以接受的复杂度。发现可以 \(\operatorname{meet in the middle}\),又喜闻乐见的发现这是一个 \(\operatorname{bool}\) 数组,所以直接用 \(\operatorname{STL::bitset}\) 代替其即可。
然后计算答案的时候,枚举前后两段的状态,然后乘法原理即可。
时间复杂度 \(O(\frac{2^{\frac{d}{2}}\times n^2}{32}+2^d)\)

代码

#include <bits/stdc++.h>
using namespace std;

const int N=100,M=(1<<11);
int n,m,d,d1,d2,ans;
bitset<N> f[M],g[M],dis[2][N];

int main()
{
	scanf("%d%d%d",&n,&m,&d);
	d2=d/2; d1=d-d2;
	for (int i=1,x,y,z;i<=m;i++)
	{
		scanf("%d%d%d",&x,&y,&z);
		dis[z][x][y]=dis[z][y][x]=1;
	}
	for (int i=n;i>=1;i--)
	{
		for (int j=0;j<M;j++)
			f[j].reset();
		f[1][i]=1;
		for (int s=1;s<(1<<d1);s++)
			for (int j=1;j<=n;j++)
				if (f[s][j]) f[s<<1]|=dis[0][j],f[(s<<1)|1]|=dis[1][j];
		for (int s=0;s<(1<<d2);s++)
			g[s][i]=f[s|(1<<d2)].any();
	}
	for (int i=0;i<(1<<d1);i++)
		for (int j=0;j<(1<<d2);j++)
			ans+=(f[(1<<d1)|i]&g[j]).any();
	printf("%d",ans);
	return 0;
}
posted @ 2020-08-13 18:27  stoorz  阅读(79)  评论(0编辑  收藏  举报