题解:SP8980 KOICOST - Cost
Aurelia_Veil · · 题解
题解:SP8980 KOICOST - Cost
不错的题目,代码与题目相互呼应,声光交融,指尖灵动,即使是我,也感到心潮澎湃。
这道题意思还是挺好懂的,我们直接开始思考。
直接求
怎么求?经过大量的数据枚举(我是真的这么做了),我们可以发现,每条边
因此,一条权值为
所以,怎么转换成代码?其实代码的写法和思路有一些差别,在我们的思考中,我们是枚举边看它对答案的贡献,然而在代码实现中,则是枚举满足
形象地说,如果一条权值为
通过集合,我们很容易就能想出,我们可以通过并查集来遍历,按边权从大到小处理。每次遇到一条边权为
代码如下:
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e5+111;
const int mod=1e9;
vector<pair<int,pair<int,int>>>edge;
int n,m;
int fa[N],siz[N];
int find(int u){
if(fa[u]!=u){
fa[u]=find(fa[u]);
}
return fa[u];
}
int make(int x,int y){
int fx=find(x);
int fy=find(y);
if(fx==fy){
return 0;
}
fa[fx]=fy;
int k=siz[fx]*siz[fy]%mod;
(siz[fy]+=siz[fx])%=mod;
return k;
}
void _init(){
for(int i=1;i<=N-11;i++){
fa[i]=i;
siz[i]=1;
}
}
signed main(){
scanf("%lld%lld",&n,&m);
_init();
int sum=0,ans=0;
for(int i=1;i<=m;i++){
int x,y,z;
scanf("%lld%lld%lld",&x,&y,&z);
edge.push_back({z,{x,y}});
sum+=z;
}
sort(edge.rbegin(),edge.rend());
for(int i=0;i<edge.size();i++){
int z=edge[i].first,x=edge[i].second.first,y=edge[i].second.second;
(ans+=make(x,y)*sum%mod)%=mod;
sum-=z;
}
printf("%lld",ans);
return 0;
}