求玄学优化做法复杂度证明
查看原帖
求玄学优化做法复杂度证明
1030875
born_to_sun楼主2024/8/9 09:32

与第一篇题解大体相同,如果不加优化复杂度是 O(n33n)O(n^33^n),我加的优化是每次枚举,只枚举 01 串的 popcount⁡\operatorname{popcount} 等于子树 sizsiz 大小的 dpdp 值。

经过本人测试:菊花图,链都卡不住。

用时 1.87s1.87s,提交记录https://www.luogu.com.cn/record/171511723

#include<bits/stdc++.h>
using namespace std;
int n,m;
int in[55][55];
vector<int> e[55];
vector<int> c[20];
long long f[17][1<<17][17];
int siz[20];
void dfs(int u,int ft){
	siz[u]=1;
	for(int i=0;i<n;i++) f[u][1<<i][i]=1;
	for(auto v:e[u]){
		if(v==ft) continue;
		dfs(v,u);
		for(auto s:c[siz[v]]){
			for(auto t:c[siz[u]]){
				if(s&t) continue;//两个01串有交就跳过
				for(int i=0;i<n;i++){
					if(!f[v][s][i]) continue;
					for(int j=0;j<n;j++){
						f[u][s^t][j]+=f[u][t][j]*f[v][s][i]*in[i][j];
					}
				}
			}

		}
		siz[u]+=siz[v];
	}
}
signed main(){
	cin>>n>>m;
	for(int i=0;i<(1<<n);i++) c[__builtin_popcount(i)].push_back(i);//优化:将符合要求的值存下来
	for(int i=1;i<=m;i++){
		int u,v;cin>>u>>v;u--;v--;in[u][v]=in[v][u]=1;
	}
	for(int i=1;i<n;i++){
		int u,v;
		cin>>u>>v;u--;v--;
		e[u].push_back(v),e[v].push_back(u);
	}
	dfs(0,-1);
	long long ans=0;
	for(int i=0;i<n;i++) ans+=f[0][(1<<n)-1][i];
	cout<<ans;
	return 0;
}

请求证明复杂度,或者构造数据卡住该做法。

2024/8/9 09:32
加载中...