题目链接
题目
An undirected graph is a set V of vertices and a set of E∈{V*V} edges.An undirected graph is connected if and only if for every pair (u,v) of vertices,u is reachable from v.
You are to write a program that tries to calculate the number of different connected undirected graph with n vertices.
For example,there are 4 different connected undirected graphs with 3 vertices.
Input
The input contains several test cases. Each test case contains an integer n, denoting the number of vertices. You may assume that 1<=n<=50. The last test case is followed by one zero.
Output
For each test case output the answer on a single line.
Sample Input
1
2
3
4
0
Sample Output
1
1
4
38
题意:
给你一个无向图,问你有多少种不同的方式使这个图连通.
思路:
n 最大是50, 所以这个题肯定会爆long long,所以需要高精度, 那么接下来就是如何计算答案了.
首先我们知道 ans[1] = ans[2] = 1;
n >= 3 时,我们考虑拿掉点 1 和点 2 的情况, 假设点 2 所在的连通块共 k 个点,这 k 个点与剩下的 n - k 个点分别处于一个连通块中, 共有ans[k] * ans[n-k] 种, 点 2 所在的连通块是需要从除去点 1 和点 2 剩下的点中选取 k-1 个点,则有C(n-2,k-1)种,而这 k 个点必须通过点 1 才能与点 1 所在的连通块相连,于是有2 ^k - 1 种,
所以答案为:
$ ans(n)=Sum(ans(k)ans(n-k) C(n-2,k-1)*( 2^k-1) | 1<=k<n )$
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 #include <algorithm> #include <cassert> #include <cstdio> #include <cstring> #include <iostream> #include <string> #include <vector> #include <cmath> using namespace std;struct BigInteger { typedef unsigned long long LL; static const int BASE = 100000000 ; static const int WIDTH = 8 ; vector<int > s; BigInteger& clean () {while (!s.back ()&&s.size ()>1 )s.pop_back (); return *this ;} BigInteger (LL num = 0 ) {*this = num;} BigInteger (string s) {*this = s;} BigInteger& operator = (long long num) { s.clear (); do { s.push_back (num % BASE); num /= BASE; } while (num > 0 ); return *this ; } BigInteger& operator = (const string& str) { s.clear (); int x, len = (str.length () - 1 ) / WIDTH + 1 ; for (int i = 0 ; i < len; i++) { int end = str.length () - i*WIDTH; int start = max (0 , end - WIDTH); sscanf (str.substr (start,end-start).c_str (), "%d" , &x); s.push_back (x); } return (*this ).clean (); } BigInteger operator + (const BigInteger& b) const { BigInteger c; c.s.clear (); for (int i = 0 , g = 0 ; ; i++) { if (g == 0 && i >= s.size () && i >= b.s.size ()) break ; int x = g; if (i < s.size ()) x += s[i]; if (i < b.s.size ()) x += b.s[i]; c.s.push_back (x % BASE); g = x / BASE; } return c; } BigInteger operator - (const BigInteger& b) const { assert (b <= *this ); BigInteger c; c.s.clear (); for (int i = 0 , g = 0 ; ; i++) { if (g == 0 && i >= s.size () && i >= b.s.size ()) break ; int x = s[i] + g; if (i < b.s.size ()) x -= b.s[i]; if (x < 0 ) {g = -1 ; x += BASE;} else g = 0 ; c.s.push_back (x); } return c.clean (); } BigInteger operator * (const BigInteger& b) const { int i, j; LL g; vector<LL> v (s.size()+b.s.size(), 0 ) ; BigInteger c; c.s.clear (); for (i=0 ;i<s.size ();i++) for (j=0 ;j<b.s.size ();j++) v[i+j]+=LL (s[i])*b.s[j]; for (i = 0 , g = 0 ; ; i++) { if (g ==0 && i >= v.size ()) break ; LL x = v[i] + g; c.s.push_back (x % BASE); g = x / BASE; } return c.clean (); } BigInteger operator / (const BigInteger& b) const { assert (b > 0 ); BigInteger c = *this ; BigInteger m; for (int i = s.size ()-1 ; i >= 0 ; i--) { m = m*BASE + s[i]; c.s[i] = bsearch (b, m); m -= b*c.s[i]; } return c.clean (); } BigInteger operator % (const BigInteger& b) const { BigInteger c = *this ; BigInteger m; for (int i = s.size ()-1 ; i >= 0 ; i--) { m = m*BASE + s[i]; c.s[i] = bsearch (b, m); m -= b*c.s[i]; } return m; } int bsearch (const BigInteger& b, const BigInteger& m) const { int L = 0 , R = BASE-1 , x; while (1 ) { x = (L+R)>>1 ; if (b*x<=m) {if (b*(x+1 )>m) return x; else L = x;} else R = x; } } BigInteger& operator += (const BigInteger& b) {*this = *this + b; return *this ;} BigInteger& operator -= (const BigInteger& b) {*this = *this - b; return *this ;} BigInteger& operator *= (const BigInteger& b) {*this = *this * b; return *this ;} BigInteger& operator /= (const BigInteger& b) {*this = *this / b; return *this ;} BigInteger& operator %= (const BigInteger& b) {*this = *this % b; return *this ;} bool operator < (const BigInteger& b) const { if (s.size () != b.s.size ()) return s.size () < b.s.size (); for (int i = s.size ()-1 ; i >= 0 ; i--) if (s[i] != b.s[i]) return s[i] < b.s[i]; return false ; } bool operator >(const BigInteger& b) const {return b < *this ;} bool operator <=(const BigInteger& b) const {return !(b < *this );} bool operator >=(const BigInteger& b) const {return !(*this < b);} bool operator !=(const BigInteger& b) const {return b < *this || *this < b;} bool operator ==(const BigInteger& b) const {return !(b < *this ) && !(b > *this );} }; ostream& operator << (ostream& out, const BigInteger& x) { out << x.s.back (); for (int i = x.s.size ()-2 ; i >= 0 ; i--) { char buf[20 ]; sprintf (buf, "%08d" , x.s[i]); for (int j = 0 ; j < strlen (buf); j++) out << buf[j]; } return out; } istream& operator >> (istream& in, BigInteger& x) { string s; if (!(in >> s)) return in; x = s; return in; } BigInteger ans[51 ],c[51 ][51 ]; void init () { for (int i = 1 ; i <= 50 ; ++i) c[i][0 ] = c[i][i] = 1 ; for (int i = 2 ; i <= 50 ; ++i) for (int j = 1 ; j < i; ++j) c[i][j] = c[i-1 ][j] + c[i-1 ][j-1 ]; ans[1 ] = ans[2 ] = 1 ; for (int i = 3 ; i <= 50 ; ++i){ for (int j = 1 ; j < i; ++j){ long long tmp = (pow (2 ,j)-1 ); ans[i] = ans[i] + ans[j] * ans[i-j]* c[i-2 ][j-1 ] * tmp; } } } int main () { init (); int n; while (scanf ("%d" , &n) && n){ cout<<ans[n]<<endl; } }