LeeCode 1617 状压 + DFS

题意

传送门 LeeCode 1617. 统计子树中城市之间最大距离

题解

考虑到节点数较少,进行状态压缩然后 O ( 2 n ) O(2^n) O(2n) 枚举子集。问题在于如何判断子集对应的节点恰好构成一颗子树,可以 D F S DFS DFS 求解,每次只向在同一个子集中的节点搜索,将状态对应二进制位赋 0 0 0,那么假如子集恰好对应一颗子树,则 D F S DFS DFS 结束时状态为 0 0 0。子树的最大路径可以在 D F S DFS DFS 的同时求解,对于每一个节点,最大路径的可能值为与根节点的路径或子树中最大的两条路径和。总复杂度 O ( n 2 n ) O(n2^n) O(n2n)

class Solution
{
#define maxn 17
public:
    vector<int> G[maxn];
    int dfs(int p, int v, int d, int &s, int &mx)
    {
        int m1 = 0, m2 = 0;
        for (int i = 0; i < G[v].size(); i++)
        {
            int u = G[v][i];
            if (u != p && (s >> u & 1))
            {
                int t = dfs(v, u, d + 1, s, mx);
                if (t > m1) swap(t, m1);
                if (t > m2) swap(t, m2);
            }
        }
        s ^= 1 << v, mx = max(mx, max(d, m1 + m2));
        return m1 + 1;
    }
    vector<int> countSubgraphsForEachDiameter(int n, vector<vector<int>> &edges)
    {
        for (auto e : edges)
        {
            int u = e[0] - 1, v = e[1] - 1;
            G[u].push_back(v);
            G[v].push_back(u);
        }
        vector<int> res(n - 1);
        for (int s = 0; s < (1 << n); s++)
        {
            for (int i = 0; i < n; i++)
            {
                if (s >> i & 1)
                {
                    int t = s, mx = 0;
                    dfs(-1, i, 0, t, mx);
                    if (!t && mx > 0)
                    {
                        ++res[mx - 1];
                    }
                    break;
                }
            }
        }
        return res;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值