比赛 |
round 2『计协冻梨桐难霍』 |
评测结果 |
AAAAAAAAAAAAAAAAA |
题目名称 |
森林还是基环树? |
最终得分 |
100 |
用户昵称 |
darkMoon |
运行时间 |
1.343 s |
代码语言 |
C++ |
内存使用 |
10.68 MiB |
提交时间 |
2024-11-22 08:17:30 |
显示代码纯文本
#include<bits/stdc++.h>
#define int long long
#define fi first
#define se second
#define mp make_pair
using namespace std;
auto mread = [](){int x;scanf("%lld", &x);return x;};
const int N = 1505, M = 2505, MOD = 1e9 + 7;
int n = mread(), m = mread(), X = mread(), Y = mread(), fa[N], d[N][N], s[N][M], g[M];
vector<pair<int, int> > v[N];
int findfa(int x){
if(x == fa[x]){
return x;
}
return fa[x] = findfa(fa[x]);
}
void dfs(int x, int fa, int root, int dis){
int y;
d[root][x] = dis;
for(auto t : v[x]){
y = t.fi;
if(y == fa){
continue;
}
dfs(y, x, root, dis + t.se);
}
return;
}
vector<vector<pair<int, int> > > v2;
int f[M];
int ksm(int x, int k){
int ans = 1, now = x;
while(k){
if(k & 1){
ans = ans * now % MOD;
}
now = now * now % MOD;
k >>= 1;
}
return ans;
}
signed main(){
for(int i = 1; i <= n; i ++){
fa[i] = i;
}
for(int i = 1, x, y, z; i <= m; i ++){
cin >> x >> y >> z;
v[x].push_back(mp(y, z));
v[y].push_back(mp(x, z));
fa[findfa(x)] = findfa(y);
}
for(int i = 1; i <= n; i ++){
dfs(i, 0, i, 0);
}
for(int i = 1; i <= n; i ++){
for(int j = i + 1; j <= n; j ++){
if(findfa(i) == findfa(j) && d[i][j] < Y){
s[findfa(i)][d[i][j]] += 2;
}
}
}
int sum = 0;
{
bool e[N] = {0};
for(int i = 1; i <= n; i ++){
if(e[findfa(i)] == 0){
e[findfa(i)] = 1;
sum ++;
}
}
}
Y -= X * sum;
for(int i = 1; i <= n; i ++){
vector<pair<int, int> > tmp;
for(int j = 0; j < Y; j ++){
if(s[i][j]){
tmp.push_back(mp(j, s[i][j]));;
}
}
if(tmp.size()){
v2.push_back(tmp);
}
}
f[0] = 1;
for(auto t : v2){
for(int j = Y - 1; j >= 0; j --){
for(auto k : t){
if(j + k.fi < Y){
g[j + k.fi] = (g[j + k.fi] + f[j] * k.se % MOD) % MOD;
}
}
}
for(int j = 0; j < Y; j ++){
f[j] = g[j];
g[j] = 0;
}
}
int sum1 = 0, sum2 = 0;
// sum: 农场个数 sum1: 所有赛道长度和 sum2: 不合法赛道长度和
for(int i = 0; i < Y; i ++){
sum2 = (sum2 + f[i] * (i + X * sum) % MOD) % MOD;
}
{
int tmp = 1, s2[n + 5] = {0};
for(int i = 1; i <= n; i ++){
s2[findfa(i)] ++;
}
for(int i = 1; i <= n; i ++){
if(s2[i]){
tmp = tmp * (s2[i] * (s2[i] - 1) % MOD) % MOD;
}
}
for(int i = 1; i <= n; i ++){
for(int j = i + 1; j <= n; j ++){
if(findfa(i) == findfa(j)){
int t2 = tmp * ksm(s2[findfa(i)] * (s2[findfa(i)] - 1) % MOD, MOD - 2) % MOD;
sum1 = (sum1 + 2ll * t2 % MOD * d[i][j] % MOD) % MOD;
}
}
}
sum1 = (sum1 + X * sum * tmp % MOD) % MOD;
}
int ans = (sum1 - sum2 + MOD) % MOD;
for(int i = 2; i <= (sum - 1); i ++){
ans = ans * i % MOD;
}
ans = ans * ksm(2, MOD - 2) % MOD;
printf("%lld", ans);
return 0;
}