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;
}

 

posted @ 2018-08-26 11:35  我只有一件白T恤  阅读(246)  评论(0编辑  收藏  举报