CF1540A Great Graphs

CF传送门

本题大意是说:给你一个长度为\(n\)的序列\({d}\)你需要构造一个有向带权图,使得点\(1\)到点\(i\)的最短路长度为\(d_i\)同时使得所有边的边权之和尽可能地小。图中不能出现负环和重边。

思路:题目要求不出现负环和重边,但没说不可以出现负权边,因此显然答案必定小于等于0
我们按照最短路长度将\(d_i\)按升序排序,
显然对于\(i\)\(i+1\)肯定有一条正权边满足\(d_{i+1}-d_i\),于此同时我们可以给\(i+1\)\(i\)添一条是这条正权边相反数的负权边
由此推广下来想,对于每个\(j\)\(i\)\(j>i\),我们都可以添一条等于\(d_j-d_i\)的相反数的负权边
预处理每相邻两点间的正权值\(c[i]=d[i]-d[i-1]\),那么每相邻两点间的这条负权边出现次数为\((n-i+1)*(i-1)\)
因此\(ans=d_n-\sum_{i=1}^nc[i]*(n-i+1)*(i-1)\)

放代码:

#include <bits/stdc++.h>
using namespace std;
const int N=1e5+10;
typedef long long ll;

int n,t,d[N],c[N];

int main(){

    cin>>t;
    while(t--){
        cin>>n;
        for(int i=1;i<=n;i++)cin>>d[i];
        sort(d+1,d+1+n);
        ll ans=d[n];
        for(int i=2;i<=n;i++) c[i]=d[i]-d[i-1];
        for(int i=1;i<=n;i++)
            ans=ans-(ll)c[i]*(n-i+1)*(i-1);
        cout<<ans<<endl;
    }

    return 0;
}

posted @ 2021-12-14 16:33  Wraith-Fiee  阅读(29)  评论(0)    收藏  举报