链接 C. Great Graphs
题意
给出大小为 n 的 a 序列,a[i]表示从 1 号点出发到 i 号点的最短距离;
构造一个图,满足 a 序列,求总的边权和最小;
思路
首先可以想到答案小于等于0
,我们只要构造 1 号点连向其余所有点边权为 a[i],再从所有点连回 1 号点边权为 -a[i],这样答案就为0了;
想要缩小这个答案,就要减少正权边的数量,增加负权边的数量
;
本题的编号其实问题不大,我们对边权进行排序,连一条最大的正权边,然后其他点由这个点去扩展,同时在 i < j 的地方连一条 j -> i 的边;
AC代码
#include <bits/stdc++.h>
#define hz020 return
#define mes memset
#define mec memcpy
#define x first
#define y second
#define pb push_back
#define be(x) (x).begin(), (x).end()
#define cl(x) memset((x), 0, sizeof (x))
#define sz(x) (int)(x).size()
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<ll,ll> PII;
const double pi = acos(-1);
const int N = 100010;
const int null = 0x3f3f3f3f,INF = 1e9;
const ll mod = 998244353;
int T;
int n;
ll a[N], sum[N];
int main()
{
cin >> T;
while (T --)
{
cin >> n;
for (int i = 1; i <= n; i ++) cin >> a[i];
sort(a + 1, a + n + 1);
ll res = 0;
for (int i = 1; i <= n; i ++) sum[i] = sum[i - 1] + a[i], res += (ll)i * a[i] - sum[i];
cout << -res + a[n] << endl;
}
hz020 0;
}