HDU 6446 Tree and Permutation(赛后补题)

时间:2023-03-10 06:34:19
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 + ;
const ll mod = 1e9 + ;
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 = ;
for (int i = ; 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 = ; i <= n; i++){
tal[i] = ; tree[i] = i;
} for (int i = ; i <= n - ; 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 - ), sum = ;
for (int i = ; 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 * % mod;
cout << sum << endl;
} return ;
}