Parametric MST
[Link](Problem - F - Codeforces)
题意
给你一个 n n n个结点的完全图,第 i i i个点的权重为 a i a_i ai,对于任意两个点的边权 w i , j ( t ) = a i a j + t ( a i + a j ) w_{i,j}(t)=a_ia_j+t(a_i+a_j) wi,j(t)=aiaj+t(ai+aj),其中 t t t是任意一个实数, f ( t ) 是 最 小 生 成 树 的 花 费 f(t)是最小生成树的花费 f(t)是最小生成树的花费,问你 f ( t ) f(t) f(t)最小可能是多少。
思路
首先将 a a a从小到大排序,设 s s s为 a a a的前缀和,对于 t t t非常大,则权值取决于 ( a i + a j ) t (a_i+a_j)t (ai+aj)t,则此时权值为 ( a 1 ∗ ( n − 1 ) + s n − s 1 ) t (a_1*(n-1)+s_n-s_1)t (a1∗(n−1)+sn−s1)t,若 ( a 1 ∗ ( n − 1 ) + s n − s 1 ) > 0 (a_1*(n-1)+s_n-s_1)>0 (a1∗(n−1)+sn−s1)>0则为 I N F INF INF,同理若 t t t是非常小的负数,若 ( a 1 ∗ ( n − 1 ) + s n − s 1 ) < 0 (a_1*(n-1)+s_n-s_1)<0 (a1∗(n−1)+sn−s1)<0则为 I N F INF INF
其它情况我们观察一下式子 w i , j ( t ) = a i a j + t ( a i + a j ) = ( a i + t ) ( a j + t ) − t 2 w_{i,j}(t)=a_ia_j+t(a_i+a_j)=(a_i+t)(a_j+t)-t^2 wi,j(t)=aiaj+t(ai+aj)=(ai+t)(aj+t)−t2,令 b i = a i + t b_i=a_i+t bi=ai+t,则权值为 w i , j ( t ) = b i b j − t 2 w_{i,j}(t)=b_ib_j-t^2 wi,j(t)=bibj−t2,令 w i , j = b i b j w_{i,j}=b_ib_j wi,j=bibj则 f ( t ) = m s t − ( n − 1 ) t 2 f(t)=mst-(n-1)t^2 f(t)=mst−(n−1)t2,对于所有的对于任意一个 t t t,一定满足 [ 1 , i ] b i < 0 [1,i]\ b_i<0 [1,i] bi<0, [ i + 1 , n ] b i > 0 [i+1,n]\ b_i>0 [i+1,n] bi>0,对于 b i < 0 b_i<0 bi<0我们将其和 m a x ( b i ) max(b_i) max(bi)相连,对于 b i > 0 b_i>0 bi>0我们将其和 m i n ( b i ) min(b_i) min(bi)相连,这样求出来的就是最小值,通过枚举 t t t求解即可
Code
#include <bits/stdc++.h>
#define x first
#define y second
#define debug(x) cout<<#x<<":"<<x<<endl;
using namespace std;
typedef long double ld;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef unsigned long long ULL;
const int N = 2e5 + 10, M = 2 * N, INF = 0x3f3f3f3f, mod = 1e9 + 7;
const double eps = 1e-8, pi = acos(-1), inf = 1e20;
int dx[] = {-1, 0, 1, 0}, dy[] = {0, 1, 0, -1};
int h[N], e[M], ne[M], w[M], idx;
void add(int a, int b, int v = 0) {
e[idx] = b, w[idx] = v, ne[idx] = h[a], h[a] = idx ++;
}
int n, m, k;
LL a[N], sum[N];
int main() {
ios::sync_with_stdio(false), cin.tie(0);
int T;
cin >> T;
while (T -- ) {
cin >> n;
for (int i = 1; i <= n; i ++) cin >> a[i];
sort(a + 1, a + 1 + n);
for (int i = 1; i <= n; i ++) sum[i] = sum[i - 1] + a[i];
if (sum[n] - sum[1] + a[1] * (n - 1) > 0 ||
sum[n - 1] + a[n] * (n - 1) < 0) {
cout << "INF\n";
continue ;
}
LL res = -1e18;
for (int i = 1; i <= n; i ++) {
LL t = -a[i];
LL mx = a[n] + t, mn = a[1] + t;
LL ls = sum[i] + i * t, rs = sum[n] - sum[i] + (n - i) * t;
res = max(res, ls * mx + rs * mn - mn * mx - (n - 1) * t * t);
}
cout << res << '\n';
}
return 0;
}
本文探讨了一个涉及完全图和动态边权的参数化最小生成树问题,通过对节点权重进行排序并利用前缀和技巧,提出了求解最小生成树代价随参数变化规律的有效算法。
&spm=1001.2101.3001.5002&articleId=123771443&d=1&t=3&u=9059289ad3bb4ecaa2b744ef7028d83b)
44

被折叠的 条评论
为什么被折叠?



