思路
CF 思维题。
因为我们要让边权值最小,所以可以利用贪心思想先将数组 \(d\) 进行升序排序。
然后再预处理出每一条边的权重。
其次我们来想一下如何处理答案,因为这道题说图中不能出现负环和重边,所以我们可以通过加反方向负边的方法来解决这道题。
因为对于一条边,这条边之后的所有点都会与这条边之前的点连负边,它们都会经过这条边,我们就可以把这条边之前的点数与这条边之后的点数相乘,得到所有经过这条边的负边数量。
得出核心代码。
for(int i = 2; i <= n; i++){e[i] = d[i] - d[i - 1];ans += e[i] * (n - i + 1) * (i - 1) - e[i];//记得加上原边的权值
}
AC 代码
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 1e5+10;
int d[N],e[N],n,ans,T;int main(){// freopen("text.in","r",stdin);// freopen("text.out","w",stdout);ios::sync_with_stdio(0),cout.tie(0),cin.tie(0);cin>>T;while (T--){cin>>n;ans = 0;for (int i = 1; i <= n; i++){cin>>d[i];}sort(d + 1, d + n + 1);for(int i = 2; i <= n; i++){e[i] = d[i] - d[i - 1];ans += e[i] * (n - i + 1) * (i - 1) - e[i];//记得加上原边的权值}cout <<-ans<< '\n';}return 0;
}