给边,点
求所有(包含所有点)的树的方案数
n<=8
分析:
直接混dfs,bfs不好实现,因为是树,所以只要找每个节点的爸爸就行了。
枚举root,然后枚举每个节点的爸爸。
因为是树,所有爸爸不能有环,要维护。
我的错误方法:
直接模拟维护,记录一个点的所有儿子,连爸爸时把儿子传个爸爸。
错因:传给爸爸时我只传了一层,俩层的祖先没有收到,仍会成环。。。
正解:
并查集,不能有环只要判断联通性就可以了啊2333
小细节这道题不能用 dad[x]=getdad(dad[x]) 来缩短查询距离,因为你连过之后要断开连下一个爸爸,
而更新dad后,断开时自己儿子的dad已经不是自己而是断开前的祖先,破坏了图的结构
应该直接return getdad(dad【x】)
代码:
#include<cmath>
#include<algorithm>
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
//#include<ctime>
using namespace std;
int n;
//int dis[9][9];
int dad[9][9];
int fa[9];
int a[9];
//bool exist[9];
int ans;
int getdad(int x)
{
if(fa[x]==x) return x;
return getdad(fa[x]);
}
void dfs(int step,int x)
{
int i,j,k;
if(step==x) dfs(step+1,x);
else
{
if(step==n+1) {ans++;return;}
int s=getdad(step);
for(i=1;i<=n;i++)
{
int t=getdad(i);
if(s!=t&&dad[step][i])
{
fa[s]=t;
dfs(step+1,x);
fa[s]=s;
}
}
}
}
int main()
{
freopen("count.in","r",stdin);
freopen("count.out","w",stdout);
int i,j,k;
char c;
scanf("%d\n",&n);
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
c=getchar();
if(c=='1')
dad[j][i]=1;
}
c=getchar();
}
for(i=1;i<=n;i++) fa[i]=i;
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++) fa[j]=j;
dfs(1,i);
}
cout<<ans;
// cout<<clock();
return 0;
}