HDU 6446 Tree and Permutation(赛后补题)
分析:这个题是结束之后和老师他们讨论出来的,很神奇;刚写的时候一直没有注意到这个是一个树这个条件;和老师讨论出来的思路是,任意两个结点出现的次数是(n-1)!,建立这个连通图,每一条边的出现的次数是边的左结点数乘右结点数,然后右结点数又等于结点总数减去左结点数,所有我们只需要知道左节点数;画成树的样子就是,子节点的个数。这个题一定要建图,但是数据有点水,我用并查集就给A掉了。
#include<cstdio> #include<vector> #include<iostream> using namespace std; #define ll long long const int maxn = 1e5 + 10; const ll mod = 1e9 + 7; ll n, tree[maxn], tal[maxn]; struct Edge{ ll a, b, v; Edge(){} Edge(ll _a, ll _b, ll _v) :a(_a), b(_b), v(_v){} }; ll f(ll nn){ ll sum = 1; for (int i = 2; i <= nn; i++){ sum = (sum*i) % mod; } return sum; } int main(){ ll a, b, v; vector<Edge>vec; while (~scanf("%lld", &n)){ vec.clear(); for (int i = 1; i <= n; i++){ tal[i] = 1; tree[i] = i; } for (int i = 1; i <= n - 1; i++){ scanf("%lld%lld%lld", &a, &b, &v); if (a > b)swap(a, b); vec.push_back(Edge(a, b, v)); tree[b] = a; tal[a] += tal[b]; while (tree[a] != a){ //cout << a << endl; a = tree[a]; tal[a] += tal[b]; } } /* (int i = 1; i <= n; i++){ cout << "tal[i] = " << tal[i] << endl; }*/ ll _n = f(n - 1), sum = 0; for (int i = 0; i < vec.size(); i++){ sum = (sum + vec[i].v*(tal[vec[i].b] * (n - tal[vec[i].b])) % mod) % mod; } sum = sum*_n%mod; sum = sum * 2 % mod; cout << sum << endl; } return 0; }