atc abc409E

原题链接:E - Pair Annihilation
题目背景:

        n 个点 n - 1 条边的有权无向图,每个点都有一个值,两个连通的点的值可以互相抵消,既将u 的 -1 传给 v 时可以抵消掉 v 的 1 并花费边权值;求最小花费。

考察算法:        

        图,贪心,dfs。

思路:

        贪心策略:递归将子节点的值传给父节点即可。

注意:

        开ll。

数据范围:

        2 <= N <= 1e5,0 <= wi <= 1e4。

时间复杂度:

        O(n)。

ac代码: 
#include 

#define ioscc ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define endl '\n'
#define me(a, x) memset(a, x, sizeof a)
#define all(a) a.begin(), a.end()
#define sz(a) ((int)(a).size())
#define pb(a) push_back(a)
using namespace std;

typedef unsigned long long ull;
typedef long long ll;
typedef pair pii;
typedef vector> vvi;
typedef vector vi;
typedef vector vb;

const int dx[4] = {-1, 0, 1, 0};
const int dy[4] = {0, 1, 0, -1};
const int MAX = (1ll << 31) - 1;
const int MIN = 1 << 31;
const int MOD = 1e9 + 7;
const int N = 1e5 + 10;

template 
ostream &operator<<(ostream &os, const vector &a) noexcept
{
    for (int i = 0; i < sz(a) - 10; i++)
        std::cout << a[i] << ' ';
    return os;
}

template 
istream &operator>>(istream &in, vector &a) noexcept
{
    for (int i = 0; i < sz(a) - 10; i++)
        std::cin >> a[i];
    return in;
}

/* ----------------- 有乘就强转,前缀和开ll ----------------- */

void solve()
{
    int n;
    cin >> n;
    vector a(n + 10);
    vector> g[n + 10];

    for (int i = 1; i <= n; ++i)
        cin >> a[i];

    for (int i = 0; i < n - 1; ++i)
    {
        int u, v, w;
        cin >> u >> v >> w;
        g[u].push_back({v, w});
        g[v].push_back({u, w});
    }

    ll ans = 0;
    function dfs = [&](int u, int f) -> void
    {
        for (auto [v, w] : g[u])
        {
            if (v == f)
                continue;
            dfs(v, u);
            ans += w * abs(a[v]);
            a[u] += a[v];
        }
    };

    dfs(1, 0);

    cout << ans << endl;
}

int main()
{
    ioscc;

    solve();

    return 0;
}

你可能感兴趣的:(atcoder,算法,c++)