1. 程式人生 > >洛谷P2014 選課

洛谷P2014 選課

.org add clu sin etc i++ con inline 有用

傳送門啦

一個樹上dp(樹上背包問題),我用了兩個方法,都A掉了,這個題數據可能太水了,第一次打錯了都A了,不過錯誤已經改掉了。

第一次就是用的樹上背包,差不多是裸題了吧。

$ f[i][j] $ 表示以 $ i $ 為根的子樹中選 $ j $ 個的最優方案,因為我們建立了一個虛點,所以最後用了 $ f[0][m+1]
$

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 305;

inline int read(){
    char ch = getchar();
    int f = 1 ,x = 0;
    while(ch > '9' || ch < '0'){if(ch == '-')f = -1;ch = getchar();}
    while(ch >= '0' && ch <= '9'){x = (x << 1) + (x << 3) + ch - '0';ch = getchar();}
    return x * f;
}

int n,m,u,w[maxn];
int head[maxn],tot;
int f[maxn][maxn],size[maxn];

struct Edge{
    int from,to,next,val;
}edge[maxn << 1];

void add(int u,int v){
    edge[++tot].from = u;
    edge[tot].to = v;
    edge[tot].next = head[u];
    head[u] = tot;
}

void dfs(int x,int fa){
    size[x] = 1;
    f[x][1] = w[x];
    for(int i=head[x];i;i=edge[i].next){
        int v = edge[i].to;
        if(v != fa){
            dfs(v , x);
            size[x] += size[v];
            for(int j=size[x];j>=2;j--)
                for(int k=0;k<=size[v];k++)
                    if(j > k)
                        f[x][j] = max(f[x][j] , f[x][j-k] + f[v][k]);
        }
    }
}           

int main(){
    n = read(); m = read();
    for(int i=1;i<=n;i++){
        u = read(); w[i] = read();
        add(u , i); add(i , u);
    }
    dfs(0 , -1);
    printf("%d\n",f[0][m+1]);
    return 0;
}   

這個 $ dfs $ 是以 $ x $ 為根,還剩下 $ t $ 個課程可以選,這個 $ f $ 數組沒有包含根節點,所以最後沒有用 $ m + 1 $ .

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 305;

inline int read(){
    char ch = getchar();
    int f = 1 ,x = 0;
    while(ch > '9' || ch < '0'){if(ch == '-')f = -1;ch = getchar();}
    while(ch >= '0' && ch <= '9'){x = (x << 1) + (x << 3) + ch - '0';ch = getchar();}
    return x * f;
}

int n,m,u,w[maxn];
int head[maxn],tot;
int f[maxn][maxn];

struct Edge{
    int from,to,next;
}edge[maxn << 1];

void add(int u,int v){
    edge[++tot].from = u;
    edge[tot].to = v;
    edge[tot].next = head[u];
    head[u] = tot;
}

void dfs(int x,int t){
    if(t == 0)  return ;
    for(int i=head[x];i;i=edge[i].next){
        int v = edge[i].to;
        for(int k=0;k<=t;k++)
            f[v][k] = f[x][k] + w[v];
        dfs(v , t - 1);
        for(int k=1;k<=t;k++)
            f[x][k] = max(f[x][k] , f[v][k-1]); 
    }
}

int main(){
    n = read(); m = read();
    for(int i=1;i<=n;i++){
        u = read(); w[i] = read();
        add(u , i);
    }
    dfs(0 , m);
    printf("%d\n",f[0][m]);
    return 0;
}

洛谷P2014 選課