Given a tree composed of n (n <= 50000) points, it is colored by m (m <= 100000) and the question is not repeated (by rotation) the number of dyeing methods.
Question: This question is completely understandable by People's code...
First, find the center of the tree (not the center of gravity). The center is defined as the midpoint of the tree's diameter. If the number of nodes on the diameter is an even number, create a new node in the center.
Then obtain the corresponding hash value for each subtree from the central dfs (hash method: hash [I] = A * (hash [j1] * B) ^ hash [j2] * B ..... ^ hash [jn] * C % D; (sequential execution )),
After sorting, the sub-trees with homogeneous structures must be arranged in adjacent locations. In this way, the x1 + x2 + ...... + Xans [I] = cnt get the number of methods used to dye the child tree of the current shape, and then get the final answer.
The correctness of the dot-point dfs is described below:
Define attribute x: when a father node whose root node fa is u, any hash [son] is not equal to hash [fa] (hash value of the upper subtree ).
If the midpoint dfs is obtained, the nature of all dfs nodes is satisfied. longest [I] is defined as the maximum distance from the root node to the leaf node with I as the diameter of the tree.
Because longest [fa] (top subtree & fa! = Center)> = l/2, longest [I] <l/2, so the x property is satisfied. In this way, the correctness is guaranteed and the homogeneous subtree is not omitted.
Sure original, reprinted please indicate the source.
[Cpp]
# Include <iostream>
# Include <cstdio>
# Include <memory. h>
# Include <algorithm>
Using namespace std;
Const int maxn = 50005;
Const int maxm = 100002;
Const int leaf = 9778972;
Const int yin = 10003;
Const int yyyy = 131237;
Const int mod = 1000000007;
Struct node
{
Int v;
Int next;
} Edge [maxn <1];
Struct H
{
_ Int64 hash, ans;
Bool operator <(const H & other) const
{
Return hash <other. hash;
}
} Val [maxn];
Int head [maxn], down [maxn], longest [maxn];
_ Int64 ans [maxn], hash [maxn], A [maxm];
Int m, n, bj, idx, root, path;
Void prepare ()
{
A [0] = A [1] = 1;
For (int I = 2; I <maxm; I ++)
{
A [I] = A [I-1] * I;
A [I] % = mod;
}
Return;
}
Void init ()
{
Memset (head,-1, sizeof (head ));
Memset (down,-1, sizeof (down ));
Idx = path = 0;
Bj = root =-1;
Return;
}
Void addedge (int u, int v)
{
Edge [idx]. v = v;
Edge [idx]. next = head [u];
Head [u] = idx ++;
Edge [idx]. v = u;
Edge [idx]. next = head [v];
Head [v] = idx ++;
Return;
}
Void read ()
{
Int u, v;
For (int I = 1; I <n; I ++)
{
Scanf ("% d", & u, & v );
Addedge (u, v );
}
Return;
}
_ Int64 powmi (_ int64 a, int x)
{
_ Int64 res = 1;
While (x)
{
If (x & 1)
{
Res * =;
Res % = mod;
}
A * =;
A % = mod;
X> = 1;
}
Return res;
}
_ Int64 C (_ int64 n, int m)
{
If (n = 1LL * m) return 1LL;
_ Int64 res = 1;
For (int I = 1; I <= m; I ++)
{
Res * = 1LL * (n-I + 1 );
Res % = mod;
}
Res * = powmi (A [m], mod-2 );
Return res % mod;
}
Void DFS (int st, int pre)
{
Int l = 0, ll = 0;
For (int I = head [st]; I! =-1; I = edge [I]. next)
{
If (edge [I]. v = pre) continue;
DFS (edge [I]. v, st );
If (longest [edge [I]. v]> l)
{
Ll = l;
L = longest [edge [I]. v];
Down [st] = I;
}
Else if (longest [edge [I]. v]> ll) ll = longest [edge [I]. v];
}
If (l + ll + 1> path)
{
Path = l + ll + 1;
Root = st;
}
Longest [st] = l + 1;
Return;
}
Void make ()
{
DFS (1, 0 );
If (path & 1)
{
While (longest [root] * 2-1> path)
{
Root = edge [down [root]. v;
}
Ans [root] = 1LL * m;
}
Else
{
While (longest [root] * 2-2> path)
{
Root = edge [down [root]. v;
}
Addedge (root, ++ n );
Addedge (n, edge [down [root]. v );
Bj = down [root];
Root = n;
Ans [root] = 1LL;
}
Return;
}
Void dfs (int st, int pre)
{
Int num = 0;
For (int I = head [st]; I! =-1; I = edge [I]. next)
{
If (edge [I]. v = pre) continue;
If (bj! =-1 & (I = bj | I = (bj ^ 1) continue;
Num ++;
Ans [edge [I]. v] = 1LL * m;
Dfs (edge [I]. v, st );
}
If (num = 0)
{
Hash [st] = leaf;
Return;
}
Int c = 0;
For (int I = head [st]; I! =-1; I = edge [I]. next)
{
If (edge [I]. v = pre) continue;
If (bj! =-1 & (I = bj | I = (bj ^ 1) continue;
Val [c]. hash = hash [edge [I]. v];
Val [c ++]. ans = ans [edge [I]. v];
}
Sort (val, val + num );
Hash [st] = leaf;
For (int I = 0; I <num ;)
{
Int j = I;
For (; j <num & val [I]. hash = val [j]. hash; j ++)
{
Hash [st] * = yin;
Hash [st] ^ = val [j]. hash;
Hash [st] % = mod;
}
Hash [st] = hash [st] * yy % mod;
Ans [st] * = C (val [I]. ans + j-I-1, j-I );
Ans [st] % = mod;
I = j;
}
Return;
}
Int main ()
{
Prepare ();
While (~ Scanf ("% d", & n, & m ))
{
Init ();
Read ();
Make ();
Dfs (root, 0 );
Printf ("% I64d \ n", ans [root]);
}
Return 0;
}