Codeforces Round #728 (Div. 2) C. Great Graphs


Great Graphs

題意

給你一個數組\(d\)\(d[i]\)表示從節點\(1\)到其他各個節點的最短路的長度,然后你可以對這個圖進行加邊(可以是負邊),但不允許存在一個權值和為負數的回路。

題解

按樣例的思想,大概就是將這些點按距離\(1\)的距離從小到大排個序,這樣就使得所有點連成一條直線,這樣總是可以保證加最多的負邊,然后就開始加負邊,對於每個點,將他和他前面的點全連上,這樣就可以保證加足夠多的負邊且沒有負環。

然后就是計算,很簡單的一個推公式,很容易知道,相鄰的兩個是互相抵消的,不需要計算,設\(S_i\)表示節點\(i\)到節點\(1\)的距離(排序后),則

\[ans=\sum_{i=1}^n\sum_{j=i+2}^n(S_j-S_i) \]

硬算的話肯定時間超了,於是對\(S_i\)\(S_j\)分開計算,對於\(S_i\),它總共被計算了\(n-i-1\)次,最多計算到\(S_{n-2}\)。對於\(S_j\),它總共被計算了\(j-2\)次,從\(S_3\)開始計算,於是上式又可以寫為

\[ans=\sum_{i=1}^{n-2}(n-i-1)(S_{n-i+1}-S_i) \]

AC代碼

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <iomanip>
#include <cstdio>
#include <vector>
#include <cmath>
#include <stack>
#include <cstring>
#include <map>
#include <set>

#define IO ios::sync_with_stdio(NULL)
#define sc(z) scanf("%d", &(z))
#define _ff(i, a, b) for (ll i = a; i <= b; ++i)
#define _rr(i, a, b) for (ll i = b; i >= a; --i)
#define _f(i, a, b) for (ll i = a; i < b; ++i)
#define _r(i, a, b) for (ll i = b - 1; i >= a; --i)
#define mkp make_pair
#define endl "\n"
#define lowbit(x) x&(-x)

using namespace std;
typedef long long ll;
typedef long double ld;

const int N = 1e5 + 5;
const ll mod = 1e9 + 7;
const ld EPS = 1e-8;

ll d[N];

int main() {
    IO;
    int T; cin >> T;
    while (T--) {
        ll n; cin >> n;
        _ff(i,  1, n) cin >> d[i];
        sort(d + 1, d + 1 + n);
        ll ans = 0;
        _ff(i, 1, n - 2) {
            ans += (n - i - 1) * (d[n - i + 1] - d[i]);
        }
        // ans -= d[n];
        if (ans) cout << "-";
        cout << ans << endl;
    }
    return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM