Submission #442594

#TimeUsernameProblemLanguageResultExecution timeMemory
442594Haruto810198Road Closures (APIO21_roads)C++17
42 / 100
245 ms53284 KiB
#include <bits/stdc++.h>

using namespace std;

#define int long long
#define double long double

#define FOR(i,l,r,d) for(int i=(l);i<=(r);i+=(d))
#define szof(x) ((int)(x).size())

#define vi vector<int>
#define pii pair<int,int>

#define F first
#define S second

#define pb push_back
#define eb emplace_back
#define mkp make_pair

#define lsb(x) ((x)&(-(x))

const int INF = 2147483647;
const int LNF = 4e18;
const int MOD = 1000000007;
const int mod = 998244353;
const double eps = 1e-12;

//#pragma GCC optimize("Ofast")
//#pragma GCC optimize("unroll-loops")

const int MAX = 100010;

int n;
vector<pii> edge[MAX]; /// original tree
int deg[MAX]; /// degree of vertices

pii par[MAX]; /// parent and childs of vectices, on the original tree
vector<pii> ch[MAX];

vi induced[MAX]; /// vectices of each induced subgraph
pii par_induced[MAX]; /// parent and childs of vectices, on the induced subgraph
vector<pii> ch_induced[MAX];

int dep[MAX]; /// depth of vectices
vi ord; /// order of dp
int dp[MAX][2]; /// dp[vertex][is connnected to parent]

int edge_cnt[MAX][11];

void edge_cnt_modify(int v, int pos, int val){
    edge_cnt[v][pos] += val;
}

int edge_cnt_query(int v, int q){
    int ret = 0;
    FOR(i, 1, 10, 1){
        ret += i * min(q, edge_cnt[v][i]);
        q = max((int)0, q - edge_cnt[v][i]);
    }
    if(q > 0) return LNF;
    return ret;
}

/// calculate dep[], par[], ch[]
void dfs(int v, pii pv, int cdep){

    par[v] = pv;
    dep[v] = cdep;

    for(pii e : edge[v]){
        int i = e.F;
        int w = e.S;
        if(i == pv.F) continue;
        ch[v].pb(e);
        dfs(i, mkp(v, w), cdep + 1);
    }

}

bool cmp_by_dep(int u, int v){
    return (dep[u] < dep[v]);
}

/// solve for induced subgraph k
int solve(int k){

    for(int v : induced[k]){
        par_induced[v] = mkp(v, 0);
        ch_induced[v].clear();
    }

    /// update edges in induced subgraph k
    for(int v : induced[k]){
        int u = par[v].F;
        int w = par[v].S;
        if(v!=u and deg[u]>k){
            par_induced[v] = mkp(u, w);
            ch_induced[u].eb(v, w);
            edge_cnt_modify(v, w, -1);
            edge_cnt_modify(u, w, -1);
        }
    }

    /// dp order
    ord = induced[k];
    sort(ord.begin(), ord.end(), cmp_by_dep);
    reverse(ord.begin(), ord.end());

    /*
    cerr<<"solve("<<k<<") : ";
    for(int v : ord){
        cerr<<v<<" ";
    }
    cerr<<endl;
    */

    /// dp

    int ret = 0;

    for(int v : ord){

        //cerr<<"dp["<<v<<"] : "<<endl;

        int ori_cost = 0; /// original cost if don't pick any child
        int n_sum = 0, n_cnt = 0; /// sum, n. of negative cost child

        /// cost of picking each child
        vi cost_ch;
        for(pii e : ch_induced[v]){
            int i = e.F;
            int w = e.S;
            /// pick : dp[i][1] + w
            /// not pick : dp[i][0]
            cost_ch.pb(dp[i][1] + w - dp[i][0]);
            ori_cost += dp[i][0];
            //assert(dp[i][1] + w - dp[i][0] >= 0);
        }
        sort(cost_ch.begin(), cost_ch.end());

        for(int i : cost_ch){
            if(i >= 0) break;
            n_sum += i;
            n_cnt++;
        }

        /*
        cerr<<"cost_ch : ";
        for(int i : cost_ch){
            cerr<<i<<" ";
        }
        cerr<<endl;
        */

        /// dp[v][0]
        dp[v][0] = LNF;

        int pick = deg[v] - k; /// n. of edges must pick to close
        int cost_ch_sum = n_sum;

        FOR(pick_ch, 0, pick, 1){ /// n. of edges picked from child
            int pick_ext = pick - pick_ch; /// n. of edges picked from extra edges
            dp[v][0] = min(dp[v][0], ori_cost + cost_ch_sum + edge_cnt_query(v, pick_ext));
            if(pick_ch >= szof(cost_ch)) break;
            if(pick_ch >= n_cnt){
                cost_ch_sum += cost_ch[pick_ch];
            }
        }

        /// if v is a root in the induced graph :
        if(par_induced[v].F == v){
            ret += dp[v][0];
            continue;
        }

        /// dp[v][1]
        dp[v][1] = LNF;

        pick = deg[v] - k - 1;
        cost_ch_sum = n_sum;

        FOR(pick_ch, 0, pick, 1){ /// n. of edges picked from child
            int pick_ext = pick - pick_ch; /// n. of edges picked from extra edges
            dp[v][1] = min(dp[v][1], ori_cost + cost_ch_sum + edge_cnt_query(v, pick_ext));
            if(pick_ch >= szof(cost_ch)) break;
            if(pick_ch >= n_cnt){
                cost_ch_sum += cost_ch[pick_ch];
            }
        }

    }

    /// recover edge_cnt
    for(int v : induced[k]){
        int u = par[v].F;
        int w = par[v].S;
        if(v!=u and deg[u]>k){
            edge_cnt_modify(v, w, 1);
            edge_cnt_modify(u, w, 1);
        }
    }

    /*
    cerr<<"dp : "<<endl;
    for(int v : induced[k]){
        cerr<<"dp["<<v<<"][0] = "<<dp[v][0]<<"\t dp["<<v<<"][1] = "<<dp[v][1]<<endl;
    }
    cerr<<endl;
    */

    return ret;

}

vi minimum_closure_costs(signed N, vector<signed> U, vector<signed> V, vector<signed> W){

    int wsum = 0;

    /// input
    n = N;
    FOR(i, 0, n-2, 1){
        int u = U[i], v = V[i], w = W[i];
        edge[u].eb(v, w);
        edge[v].eb(u, w);
        deg[u]++;
        deg[v]++;
        edge_cnt_modify(u, w, 1);
        edge_cnt_modify(v, w, 1);
        wsum += w;
    }

    /// dfs
    dfs(0, mkp(0, 0), 0);

    /*
    cerr<<"par : "<<endl;
    FOR(i, 0, n-1, 1){
        cerr<<"par["<<i<<"] = ("<<par[i].F<<", "<<par[i].S<<")"<<endl;
    }
    cerr<<endl;

    cerr<<"ch : "<<endl;
    FOR(i, 0, n-1, 1){
        cerr<<"ch["<<i<<"] = ";
        for(pii e : ch[i]){
            cerr<<"("<<e.F<<", "<<e.S<<") ";
        }
        cerr<<endl;
    }
    cerr<<endl;

    cerr<<"dep : "<<endl;
    FOR(i, 0, n-1, 1){
        cerr<<"dep["<<i<<"] = "<<dep[i]<<endl;
    }
    cerr<<endl;
    */

    /// induced subgraph
    FOR(i, 0, n-1, 1){
        FOR(j, 0, deg[i]-1, 1){
            induced[j].pb(i);
        }
    }

    /// solve for each induced subgraph
    vi res(n);
    res[0] = wsum;
    FOR(i, 1, n-1, 1){
        res[i] = solve(i);
    }

    return res;

}

/*
signed main(){

    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    //vi res = minimum_closure_costs(4, {0, 2, 0}, {1, 0, 3}, {5, 10, 5});
    //vi res = minimum_closure_costs(5, {0, 0, 0, 2}, {1, 2, 3, 4}, {1, 4, 3, 2});
    vi res = minimum_closure_costs(6, {0, 1, 2, 3, 4}, {1, 2, 3, 4, 5}, {1, 10, 1, 10, 1});

    cerr<<"res : ";
    for(int i : res){
        cerr<<i<<" ";
    }
    cerr<<endl;

    return 0;

}
*/

#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...