HDU 4013 Distinct Subtrees(树同构)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4013

题意:给定一棵树,求不同的子树的个数。

思路:枚举每个点集,DFS求最小表示。对于某一种情况,若有一次得到的表示以前没有,答案加1。你可能会想,如果这种情况可以得到一棵森林呢,这样的话森林中的每棵树在之前肯定插入了,因为你是按照状态枚举的,单棵树的状态肯定小于森林的状态。

#include <iostream>

#include <string>

#include <vector>

#include <set>

#include <cstring>

#include <cstdio>

#include <algorithm>

using namespace std;



int g[15][15],n,C,num=0,visit[15];

set<string> S;





string DFS(int u,int pre)

{

    int i;

    string s="0";

    vector<string> V;

    for(i=0;i<n;i++) if(g[u][i]&&i!=pre&&visit[i])

        V.push_back(DFS(i,u));

    sort(V.begin(),V.end());

    for(i=0;i<V.size();i++) s+=V[i];

    s+="1";

    return s;

}



void deal()

{

    int i,j,flag,ans=0;

    string str;

    for(i=0;i<(1<<n);i++)

    {

        memset(visit,0,sizeof(visit));

        for(j=0;j<n;j++) if(i&(1<<j)) visit[j]=1;

        flag=0;

        for(j=0;j<n;j++) if(visit[j])

        {

            str=DFS(j,-1);

            if(S.find(str)==S.end()) flag=1,S.insert(str);

        }

        ans+=flag;

    }

    printf("%d\n",ans);

}



int main()

{

    for(scanf("%d",&C);C--;)

    {

        scanf("%d",&n);

        memset(g,0,sizeof(g));

        int i,u,v;

        for(i=1;i<n;i++)

        {

            scanf("%d%d",&u,&v);

            u--;v--;

            g[u][v]=g[v][u]=1;

        }

        S.clear();

        printf("Case #%d: ",++num);

        deal();

    }

    return 0;

}

  

 

你可能感兴趣的:(distinct)