hdu4013树的最小表示

题意:求无根树的不同构子树的个数,树的最小表示

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#define inf (1 << 30)
#define mod 1000000007
#define N 20
const double eps = 1e-12;
const double pi = acos(-1.0);
using namespace std;

struct tire
{
    int date;
    struct tire* son[2];
}*root;

int T, n, state, ans;
int a[N], b[N], vis[N];
int g[N][N];

int init()
{
    ans = 0;
    memset(g, 0, sizeof(g));
    root = new tire;
    root -> date = 0;
    root -> son[0] = NULL;
    root -> son[1] = NULL;
    return 1;
}

int insert(string s, struct tire *p)
{
    int i;
    struct tire *rot = p;
    for (i = 0; i < s.size(); i++)
    {
        if (rot -> son[s[i] - '0'] == NULL)
        {
            tire *t = new tire;
            t -> date = 0;
            t -> son[0] = NULL;
            t -> son[1] = NULL;
            rot -> son[s[i] - '0'] = t;
        }
        rot = rot -> son[s[i] - '0'];
    }
    if (rot -> date == 1) return 0;
    rot -> date = 1;
    return 1;
}

int DFS(int t)
{
    int i;
    state = state ^ (1 << t);
    vis[t] = 1;
    for (i = 0; i < n; i++)
        if (vis[i] == 0 && ((1 << i) & state)) DFS(i);
    return 1;
}

int check()
{
    int i;
    memset(vis, 0, sizeof(vis));
    for (i = 0; i < n; i++)
        if (state & (1 << i))
        {
            DFS(i);
            break;
        }
    return 1;
}

string DFS1(int t, int p)
{
    int i, j;
    string vs = "0";
    vector<string> q;
    for (i = 0; i < n; i++)
        if (vis[i] && g[t][i] && i != p) q.push_back(DFS1(i, t));
    sort(q.begin(), q.end());
    for (i = 0; i < q.size(); i++) vs += q[i];
    vs += "1";
    return vs;
}

int solve()
{
    int i, j, f = 0, t;
    string s;
    for (i = 0; i < n; i++)
        if (vis[i] == 1)
        {
            s = DFS1(i, -1);
            t = insert(s, root);
            if ((! t) && (! f)) return 0;
            f = 1;
        }
    return 1;
}

int main()
{
    int i, j, h, x, y;
    string s;
    scanf("%d", &T);
    for (h = 1; h <= T; h++)
    {
        scanf("%d", &n);
        init();
        for (i = 1; i < n; i++)
        {
            scanf("%d%d", &x, &y);
            g[x - 1][y - 1] = g[y - 1][x - 1] = 1;
        }
        for (i = 1; i < (1 << n); i++)
        {
            state = i;
            check();
            if (state != 0) continue;
            ans += solve();
        }
        printf("Case #%d: %d\n", h, ans);
    }
    system("pause");
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值