P3177 树上染色DP求调
  • 板块学术版
  • 楼主EDGW_
  • 当前回复1
  • 已保存回复1
  • 发布时间2023/10/11 18:24
  • 上次更新2023/11/2 14:28:12
查看原帖
P3177 树上染色DP求调
1064122
EDGW_楼主2023/10/11 18:24

总体思路是这样的: 题目链接 有没有大佬看一下思路或者代码有没有问题 (过了样例)(只过了样例)

//*
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 2200;
#define int long long
int n, k, weights[MAXN][MAXN];
vector<int> children[MAXN];
int father[MAXN], sib[MAXN], size_sz[MAXN];

void addedge(int a, int b, int w) {
    children[a].push_back(b);
    children[b].push_back(a);
    weights[a][b] = weights[b][a] = w;
}
void read() {
    cin >> n >> k;
    int u, v, w;
    for (int i = 1; i < n; i++) {
        cin >> u >> v >> w;
        addedge(u, v, w);
    }
}
void preproc(int node) {
    int sz = 1;
    int lastchild = 0;
    for (int child : children[node]) {
        if (child != father[node]) {
            father[child] = node;
            if (lastchild)sib[lastchild] = child;
            lastchild = child;
            preproc(child);
            sz += size_sz[child];
        }
    }
    size_sz[node] = sz;
}
inline int c(int p, int s, int w) {
    int val = (p * (k - p) + (s - p) * (n - s - k + p)) * w;
    return val;
}
int f[MAXN][MAXN];
int g[MAXN][MAXN];
inline void calc(int node) {
    for (int child : children[node]) {
        if (child != father[node])calc(child);
    }
    //printf("calc %d\n", node);
    if (!children[node].empty()) {
        int last = children[node].size() - 1;
        int maxp = 0;
        for (int s = last; s >= 0; s--) {
            maxp += size_sz[children[node][s]];
            for (int p = 0; p <= maxp; p++) {
                for (int i = 0; i < p; i++) {
                    g[children[node][s]][p] = max(
                        g[children[node][s]][p],
                        f[children[node][s]][i] + g[sib[children[node][s]]][p - i]
                    );
                }
            }
        }
    }
    for (int p = max(k-(n- size_sz[node]),0LL); p <= size_sz[node]; p++) {
        int w = c(p, size_sz[node], weights[node][father[node]]);
        //printf("calc basic value of f[%d][%d]=%d %d:w %d of p %d\n", node, p, w, node, w, p);
        f[node][p] = w;
        if (!children[node].empty()) {
            int sb = max(g[children[node][0]][p], g[children[node][0]][p - 1]);
            //printf("calc additional value of f[%d][%d]+=%d\n", node, p, sb);
            f[node][p] += sb;
        }
    }
}
int width = 9;
inline void print_f(int f[MAXN][MAXN]) {
    cout << setw(width) << "i\\j";
    for (int i = 0; i <= k; i++) {
        cout << setw(width) << i;
    }
    cout << endl;
    for (int i = 1; i <= n; i++)
    {
        cout << setw(width) << i;
        for (int j = 0; j <= k; j++) {
            cout << setw(width) << f[i][j];
        }
        cout << endl;
    }
}
signed main() {
    read();
    father[1] = 1;
    preproc(1);
    calc(1);
    /*printf("f\n");
    print_f(f);
    printf("g\n");
    print_f(g);*/
    cout << f[1][k];
}
//*/


/*
//by Judge
#include<cstdio>
#include<cctype>
#define ll long long
#define rint register int
#define max(a,b) ((a)>(b)?(a):(b))
using namespace std;
const int M = 2100;
inline ll read() {
    ll x = 0, f = 1; char c = getchar();
    for (; !isdigit(c); c = getchar()) if (c == '-') f = -1;
    for (; isdigit(c); c = getchar()) x = x * 10 + c - '0';
    return x * f;
}
int n, k, pat;
int head[M];
ll siz[M], dp[M][M], tmp;
struct Edge 
{
    Edge(int a,int b,ll c):to(a),next(b),val(c){}
    Edge(){}
    int to, next; ll val;
}e[M << 1];
inline void add(rint u, rint v, rint c) { e[++pat] = Edge(v,head[u],c), head[u] = pat; }
void dfs(rint u) {
    siz[u] = 1;
    for (rint i = head[u]; i; i = e[i].next) {
        rint v = e[i].to; if (siz[v]) continue;
        dfs(v); ll c = e[i].val;
        for (rint a = siz[u]; a >= 0; --a)  //枚举当前点的以及当前点的其他子树的染色点数 (反向枚举,避免后效性) 
            for (rint b = siz[v]; b >= 0; --b)  //枚举目前处理的子树的染色点数 
                tmp = dp[u][a] + dp[v][b] + c * b * (k - b) + c * (n - k + b - siz[v]) * (siz[v] - b), dp[u][a + b] = max(dp[u][a + b], tmp);
        // dp[u][a] 其他子树内的点各自独立于当前子树内的点的贡献 
        //dp[v][b] 当前子树内的点各自独立于其他子树内的点的贡献 
        //c*b*(k-b) 当前边对连接当前子树内的染色点与子树外的染色点的贡献
        //c*(n-k+b-siz[v])*(siz[v]-b) 当前边对连接当前子树内的未染色点与子树外的未染色点的贡献 
        siz[u] += siz[v];
    }
}
int main() {   //主函数里尽是朴素操作
    n = read(), k = read();
    for (rint i = 1; i < n; ++i) {
        rint x = read(), y = read(); ll c = read();
        add(x, y, c), add(y, x, c);
    }
    dfs(1), printf("%lld\n", dp[1][k]);
    return 0;
}
//*/
2023/10/11 18:24
加载中...