Submission #1361439

#TimeUsernameProblemLanguageResultExecution timeMemory
1361439po_rag526Toll (APIO13_toll)C++17
16 / 100
1 ms3152 KiB
#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
const int MAXN = 100005, MAXM = 300005, MAXK = 22;

struct Edge {
    int u, v, w, id;
    bool operator<(const Edge& o) const { return w < o.w; }
} old_edges[MAXM];

int N, M, K;
ll pop[MAXN];               // ??????
int new_u[MAXK], new_v[MAXK];

// ???
struct DSU {
    int parent[MAXN];
    void init(int n) { for(int i=1;i<=n;++i) parent[i]=i; }
    int find(int x) { return parent[x]==x ? x : parent[x]=find(parent[x]); }
    bool unite(int x,int y) { x=find(x); y=find(y); if(x==y) return 0; parent[y]=x; return 1; }
};

// MST ???
struct TreeEdge { int to, id; };
vector<TreeEdge> tree[MAXN];

int depth[MAXN], up[MAXN][18], max_edge_id[MAXN][18];
ll sub_pop[MAXN];           // ?????
int edge_to_parent[MAXN];   // ???????id
int edge_w[MAXM];           // ????
ll edge_pop[MAXM];          // ???????????

// DFS ???????????????id?????
void dfs(int u, int p, int d) {
    depth[u] = d;
    up[u][0] = p;
    for (int i = 1; i < 18; ++i) {
        up[u][i] = up[ up[u][i-1] ][i-1];
        int mid = up[u][i-1];
        int e1 = max_edge_id[u][i-1];
        int e2 = max_edge_id[mid][i-1];
        max_edge_id[u][i] = (edge_w[e1] >= edge_w[e2]) ? e1 : e2;
    }
    for (size_t i = 0; i < tree[u].size(); ++i) {
        int v = tree[u][i].to;
        if (v == p) continue;
        edge_to_parent[v] = tree[u][i].id;
        max_edge_id[v][0] = tree[u][i].id;
        dfs(v, u, d + 1);
        sub_pop[u] += sub_pop[v];
    }
}

// ????(u,v)??????????id
int query_max_edge(int u, int v, int& max_id) {
    if (depth[u] < depth[v]) swap(u, v);
    int diff = depth[u] - depth[v];
    max_id = 0; edge_w[0] = 0;          // ??????0
    for (int i = 0; diff; ++i, diff >>= 1)
        if (diff & 1) {
            if (edge_w[max_edge_id[u][i]] > edge_w[max_id])
                max_id = max_edge_id[u][i];
            u = up[u][i];
        }
    if (u == v) return edge_w[max_id];
    for (int i = 17; i >= 0; --i)
        if (up[u][i] != up[v][i]) {
            if (edge_w[max_edge_id[u][i]] > edge_w[max_id]) max_id = max_edge_id[u][i];
            if (edge_w[max_edge_id[v][i]] > edge_w[max_id]) max_id = max_edge_id[v][i];
            u = up[u][i]; v = up[v][i];
        }
    if (edge_w[max_edge_id[u][0]] > edge_w[max_id]) max_id = max_edge_id[u][0];
    if (edge_w[max_edge_id[v][0]] > edge_w[max_id]) max_id = max_edge_id[v][0];
    return edge_w[max_id];
}

int main() {
    scanf("%d %d %d", &N, &M, &K);
    for (int i = 1; i <= M; ++i) {
        scanf("%d %d %d", &old_edges[i].u, &old_edges[i].v, &old_edges[i].w);
        old_edges[i].id = i;
        edge_w[i] = old_edges[i].w;
    }
    for (int i = 0; i < K; ++i)
        scanf("%d %d", &new_u[i], &new_v[i]);
    for (int i = 1; i <= N; ++i)
        scanf("%lld", &pop[i]);

    // ???????????
    sort(old_edges + 1, old_edges + M + 1);
    DSU dsu; dsu.init(N);
    for (int i = 1; i <= M; ++i) {
        if (dsu.unite(old_edges[i].u, old_edges[i].v)) {
            int u = old_edges[i].u, v = old_edges[i].v;
            int id = old_edges[i].id;
            tree[u].push_back({v, id});
            tree[v].push_back({u, id});
        }
    }

    // DFS ?????1???
    for (int i = 1; i <= N; ++i) sub_pop[i] = pop[i];
    dfs(1, 0, 0);
    // ?????????????????????
    for (int i = 2; i <= N; ++i) {
        int eid = edge_to_parent[i];
        edge_pop[eid] = sub_pop[i];
    }

    // ????????????????id
    int best_id[MAXK];
    ll revenue[MAXK];
    for (int i = 0; i < K; ++i) {
        int mx_id = 0;
        /* int mx_w = */ query_max_edge(new_u[i], new_v[i], mx_id);
        best_id[i] = mx_id;
        revenue[i] = (ll)edge_w[mx_id] * edge_pop[mx_id];
    }

    // ??????????????
    ll best_income = 0;
    int total = 1 << K;
    for (int mask = 0; mask < total; ++mask) {
        bool conflict = false;
        ll sum = 0;
        for (int i = 0; i < K; ++i) if (mask & (1 << i)) {
            for (int j = i + 1; j < K; ++j) if (mask & (1 << j)) {
                if (best_id[i] == best_id[j]) { conflict = true; break; }
            }
            if (conflict) break;
            sum += revenue[i];
        }
        if (!conflict && sum > best_income)
            best_income = sum;
    }

    printf("%lld\n", best_income);
    return 0;
}

Compilation message (stderr)

toll.cpp: In function 'int main()':
toll.cpp:79:10: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
   79 |     scanf("%d %d %d", &N, &M, &K);
      |     ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
toll.cpp:81:14: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
   81 |         scanf("%d %d %d", &old_edges[i].u, &old_edges[i].v, &old_edges[i].w);
      |         ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
toll.cpp:86:14: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
   86 |         scanf("%d %d", &new_u[i], &new_v[i]);
      |         ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
toll.cpp:88:14: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
   88 |         scanf("%lld", &pop[i]);
      |         ~~~~~^~~~~~~~~~~~~~~~~
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...