Luogu P4643 [国家集训队] 阿狸和桃子的游戏 题解 [ 蓝 ] [ 边权转点权 ] [ Ad-hoc ]

阿狸和桃子的游戏:Lucyna 推荐的简单诈骗题。

直接对每次两人操作对答案的增量考虑,发现如果一条边被同一个人选择,那么贡献就是 \(w\);否则贡献就是 \(0\)。而如果把这个贡献均摊到每次给点染色的操作中,贡献就可以定为 \(\dfrac{w}{2}\)。容易发现答案就是桃子选的贡献减去阿狸选的贡献。于是把边权转点权,然后排序一下,贪心选即可。

时间复杂度 \(O(n\log n)\),用桶排序可以做到 \(O(n)\)。注意除以 \(2\) 的处理方式,可以将点权先全部乘 \(2\),最后输出答案的时候再把答案除以 \(2\) 即可。

#include <bits/stdc++.h>
#define fi first
#define se second
#define eb(x) emplace_back(x)
#define pb(x) push_back(x)
#define lc(x) (tr[x].ls)
#define rc(x) (tr[x].rs)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ldb;
using pi=pair<int,int>;
const int N = 10005;
int n, m;
ll a[N], ans;
int main()
{
    //freopen("sample.in","r",stdin);
    //freopen("sample.out","w",stdout);
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    cin >> n >> m;
    for(int i = 1; i <= n; i++)
    {
        cin >> a[i];
        a[i] = a[i] * 2;
    }
    for(int i = 1; i <= m; i++)
    {
        int u, v, w;
        cin >> u >> v >> w;
        a[u] += w;
        a[v] += w;
    }
    sort(a + 1, a + n + 1);
    for(int i = n; i >= 1; i -= 2) ans += a[i] - a[i - 1];
    cout << ans / 2;
    return 0;
}
posted @ 2025-08-05 08:10  KS_Fszha  阅读(16)  评论(0)    收藏  举报