POJ1737 Connected Graph ( n点无向连通图计数

Posted Linnyx

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ1737 Connected Graph ( n点无向连通图计数相关的知识,希望对你有一定的参考价值。

题意说明:求 \\(n\\) 个点的无向连通图个数

据说已经非常典了,但是我太菜了不会组合数学,最近补档时看到这道题,决定记录下来理理思路

POJ1737 Connected Graph

一道计数类(DP)

原题链接

我们可以用(n)个节点能构成的无向图总数减去(n)个点能构成的不连通无向图的数量即可得到答案。
因为(n)个点之间最多能有(dfrac{n imes(n-1)}{2})条边,而每次选边构成无向图,对于每一条边只有选与不选两种,所以(n)个点能构成的无向图总数为(2^{frac{n imes(n-1)}{2}})
然后我们计算(n)个点能构成的不连通无向图的数量。
我们可以枚举编号为(1)的节点所在连通块的大小(k),对于每个(k),要从剩余(n-1)个点中取出(k-1)个点来与(1)号节点构成一个连通块,共(C_{n-1}^{k-1})种方法,而剩余的(n-k)个节点则构成任意无向图,共(2^{frac{(n-k) imes(n-k-1)}{2}})种。
定义(f[i])表示(i)个节点能构成的无向图总数,有状态转移方程:

(qquadqquad f[i]=2^{frac{i imes(i-1)}{2}}-sumlimits_{j=1}^{i-1}f[j] imes C_{i-1}^{j-1} imes 2^{frac{(i-j) imes(i-j-1)}{2}})

另外,因为数据很大,需要使用高精度,这里我直接套用我以前打的高精模板,所以代码会显得很长。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N = 85;
//高精模板
struct big {
    static const int base = 100000000;
    static const int w = 8;
    ll s[N], l;
    big()
    {
        memset(s, 0, sizeof(s));
        l = -1;
    }
    big operator = (const big& b)
    {
        for (int i = 0; i < N; i++)
            s[i] = b.s[i];
        l = b.l;
        return *this;
    }
    big operator = (ll num)
    {
        memset(s, 0, sizeof(s));
        l = -1;
        do
        {
            s[++l] = num % base;
            num /= base;
        } while (num > 0);
        return *this;
    }
    big operator = (int num)
    {
        memset(s, 0, sizeof(s));
        l = -1;
        do
        {
            s[++l] = num % base;
            num /= base;
        } while (num > 0);
        return *this;
    }
    big operator + (const big& b)
    {
        big c;
        ll x = 0, i;
        c = x;
        c.l = -1;
        for (i = 0; i <= l || i <= b.l; i++)
        {
            x = x + s[i] + b.s[i];
            c.s[++c.l] = x % base;
            x /= base;
        }
        if (x)
            c.s[++c.l] = x;
        while (!c.s[c.l] && c.l > 0)
            c.l--;
        return c;
    }
    big operator + (ll b)
    {
        big c, d;
        d = b;
        c = *this + d;
        return c;
    }
    big operator + (int b)
    {
        big c, d;
        d = b;
        c = *this + d;
        return c;
    }
    big operator += (const big& b)
    {
        *this = *this + b;
        return *this;
    }
    big operator += (ll b)
    {
        big c;
        c = b;
        *this = *this + c;
        return *this;
    }
    big operator += (int b)
    {
        big c;
        c = b;
        *this = *this + c;
        return *this;
    }
    big operator - (const big& b)
    {
        big c, d;
        ll x = 0, i;
        d = *this;
        c = x;
        c.l = -1;
        for (i = 0; i <= d.l || i <= b.l; i++)
        {
            if (d.s[i] < b.s[i])
            {
                d.s[i + 1]--;
                d.s[i] += base;
            }
            c.s[++c.l] = d.s[i] - b.s[i];
        }
        while (!c.s[c.l] && c.l > 0)
            c.l--;
        return c;
    }
    big operator - (ll b)
    {
        big c, d;
        d = b;
        c = *this - d;
        return c;
    }
    big operator - (int b)
    {
        big c, d;
        d = b;
        c = *this - d;
        return c;
    }
    big operator -= (const big& b)
    {
        *this = *this - b;
        return *this;
    }
    big operator -= (ll b)
    {
        big c;
        c = b;
        *this = *this - c;
        return *this;
    }
    big operator -= (int b)
    {
        big c;
        c = b;
        *this = *this - c;
        return *this;
    }
    big operator * (const big& b)
    {
        big c;
        ll x = 0, i, j;
        c = x;
        c.l = -1;
        for (i = 0; i <= l; i++)
        {
            x = 0;
            for (j = 0; j <= b.l; j++)
            {
                c.s[i + j] = s[i] * b.s[j] + x + c.s[i + j];
                x = c.s[i + j] / base;
                c.s[i + j] %= base;
            }
            c.s[i + b.l + 1] = x;
        }
        c.l = l + b.l + 1;
        while (!c.s[c.l] && c.l > 0)
            c.l--;
        return c;
    }
    big operator * (ll b)
    {
        big c, d;
        d = b;
        c = *this*d;
        return c;
    }
    big operator * (int b)
    {
        big c, d;
        d = b;
        c = *this*d;
        return c;
    }
    big operator *= (const big& b)
    {
        *this = *this*b;
        return *this;
    }
    big operator *= (ll b)
    {
        big c;
        c = b;
        *this = *this*c;
        return *this;
    }
    big operator *= (int b)
    {
        big c;
        c = b;
        *this = *this*c;
        return *this;
    }
    big operator / (const big& b)
    {
        big cc, dd, k;
        ll x = 0, i, j, le, r, m;
        cc = x;
        cc.l = l + b.l;
        if (b.l < 1)
        {
            for (i = b.l; i >= 0; i--)
                x = x * base + b.s[i];
            cc = *this / x;
            return cc;
        }
        for (i = l; i >= 0; i--)
        {
            dd.l++;
            for (j = dd.l; j >= 1; j--)
                dd.s[j] = dd.s[j - 1];
            dd.s[0] = s[i];
            if (dd < b)
                continue;
            le = 0;
            r = 99999999;
            while (le < r)
            {
                m = (le + r) / 2;
                k = m;
                k *= b;
                if (k <= dd)
                    le = m + 1;
                else
                    r = m;
            }
            r -= 1;
            cc.s[i] = r;
            k = r;
            k *= b;
            dd -= k;
        }
        while (!cc.s[cc.l] && cc.l > 0)
            cc.l--;
        return cc;
    }
    big operator / (ll b)
    {
        big cc;
        ll x = 0, i;
        cc.l = -1;
        for (i = l; i >= 0; i--)
        {
            cc.s[i] = (x*base + s[i]) / b;
            x = (x*base + s[i]) % b;
        }
        cc.l = l;
        while (!cc.s[cc.l] && cc.l > 0)
            cc.l--;
        return cc;
    }
    big operator / (int b)
    {
        big c;
        ll x = b;
        c = *this / x;
        return c;
    }
    big operator /=(const big& b)
    {
        *this = *this / b;
        return *this;
    }
    big operator /= (ll b)
    {
        big c;
        c = b;
        *this = *this / c;
        return *this;
    }
    big operator /= (int b)
    {
        big c;
        c = b;
        *this = *this / c;
        return *this;
    }
    big operator % (const big& b)
    {
        big f, e, kk;
        ll x = 0, i, j, le, r, m;
        if (b.l < 1)
        {
            for (i = b.l; i >= 0; i--)
                x = x * base + b.s[i];
            f = *this%x;
            return f;
        }
        f = x;
        f.l = l + b.l;
        for (i = l; i >= 0; i--)
        {
            e.l++;
            for (j = e.l; j >= 1; j--)
                e.s[j] = e.s[j - 1];
            e.s[0] = s[i];
            if (e < b)
                continue;
            le = 0;
            r = 99999999;
            while (le < r)
            {
                m = (le + r) / 2;
                kk = m;
                kk *= b;
                if (kk <= e)
                    le = m + 1;
                else
                    r = m;
            }
            r -= 1;
            f.s[i] = r;
            kk = r;
            kk *= b;
            e -= kk;
        }
        while (!e.s[e.l] && e.l > 0)
            e.l--;
        return e;
    }
    big operator % (ll b)
    {
        big f, e;
        ll x = 0, i;
        f.l = -1;
        for (i = l; i >= 0; i--)
        {
            f.s[i] = (x*base + s[i]) / b;
            x = (x*base + s[i]) % b;
        }
        e = x;
        return e;
    }
    big operator % (int b)
    {
        big c;
        ll x = b;
        c = *this%x;
        return c;
    }
    big operator %= (const big& b)
    {
        *this = *this%b;
        return *this;
    }
    big operator %= (ll b)
    {
        big c;
        c = b;
        *this = *this%c;
        return *this;
    }
    big operator %= (int b)
    {
        big c;
        c = b;
        *this = *this%c;
        return *this;
    }
    bool operator < (const big& b)const
    {
        if (l != b.l)
            return l < b.l;
        for (ll i = l; i >= 0; i--)
            if (s[i] != b.s[i])
                return s[i] < b.s[i];
        return false;
    }
    bool operator > (const big& b)const
    {
        return b < *this;
    }
    bool operator <= (const big& b)const
    {
        return !(b < *this);
    }
    bool operator >= (const big& b)const
    {
        return !(*this < b);
    }
    bool operator != (const big& b)const
    {
        return b < *this || *this < b;
    }
    bool operator == (const big& b)const
    {
        return !(b < *this) && !(*this < b);
    }
    bool operator < (ll b)const
    {
        big d;
        d = b;
        return *this < d;
    }
    bool operator > (ll b)const
    {
        big d;
        d = b;
        return d < *this;
    }
    bool operator <= (ll b)const
    {
        big d;
        d = b;
        return !(d < *this);
    }
    bool operator >= (ll b)const
    {
        big d;
        d = b;
        return !(*this < d);
    }
    bool operator != (ll b)const
    {
        big d;
        d = b;
        return d < *this || *this < d;
    }
    bool operator == (ll b)const
    {
        big d;
        d = b;
        return !(d < *this) && !(*this < d);
    }
    bool operator < (int b)const
    {
        big d;
        d = b;
        return *this < d;
    }
    bool operator > (int b)const
    {
        big d;
        d = b;
        return d < *this;
    }
    bool operator <= (int b)const
    {
        big d;
        d = b;
        return !(d < *this);
    }
    bool operator >= (int b)const
    {
        big d;
        d = b;
        return !(*this < d);
    }
    bool operator != (int b)const
    {
        big d;
        d = b;
        return d < *this || *this < d;
    }
    bool operator == (int b)const
    {
        big d;
        d = b;
        return !(d < *this) && !(*this < d);
    }
};
//以上为高精模板
big f[N], fac[N], po[1230];
int re()
{
    int x = 0;
    char c = getchar();
    bool p = 0;
    for (; c<'0' || c>'9'; c = getchar())
        p = (c == '-' || p) ? 1 : 0;
    for (; c >= '0'&&c <= '9'; c = getchar())
        x = x * 10 + (c - '0');
    return p ? -x : x;
}
void pr(int x)
{
    int i;
    printf("%lld", f[x].s[f[x].l]);
    for (i = f[x].l - 1; i >= 0; i--)
        printf("%08lld", f[x].s[i]);
    printf("
");
}
big C(int x, int y)
{
    return fac[y] / fac[x] / fac[y - x];
}
int main()
{
    int i, n, j;
    fac[0] = f[1] = po[0] = 1;
    for (i = 1; i <= 50; i++)
        fac[i] = fac[i - 1] * i;
    for (i = 1; i <= 1225; i++)
        po[i] = po[i - 1] * 2;
    for (i = 2; i <= 50; i++)
    {
        f[i] = po[(i*(i - 1)) >> 1];
        for (j = 1; j < i; j++)
            f[i] -= f[j] * C(j - 1, i - 1)*po[((i - j)*(i - j - 1)) >> 1];
    }
    while (1)
    {
        n = re();
        if (!n)
            return 0;
        pr(n);
    }
    return 0;
}

ps:因为我用的是(VS),所以代码会自动补空格,而我本来的风格是没有空格的。

以上是关于POJ1737 Connected Graph ( n点无向连通图计数的主要内容,如果未能解决你的问题,请参考以下文章

POJ 1737 Connected Graph 题解(未完成)

poj1737 Connected Graph

POJ1737 Connected Graph

POJ1737 Connected Graph ( n点无向连通图计数

$Poj1737 Connected Graph$ 计数类$DP$

poj1737-----这题有毒