1. 程式人生 > >P2286 [HNOI2004]寵物收養場

P2286 [HNOI2004]寵物收養場

題意 per 應該 scan void 可用 play 一個 spl

第一次用set水splay好爽啊!


這道題很明顯,就是弄兩個平衡樹(一個也可以)。

進來一個人,就去另一邊找找前驅和後繼,優先找前驅,找個絕對值最小的配對走。

其實用一下set就可以了啊!

使用std::set.lower_bound就可以找到x元素,--一下就得到前驅,++一下應該就得到了後繼。

其實後繼也直接可用upper_bound

再根據題意模擬一下就能過了。。。

這道題數據特別水。。。

代碼:

#include<cstdio>
#include<algorithm>
const int maxn = 1005;
struct Edges
{
    int next, to, weight;
} e[maxn];
int head[maxn], tot;
int dp[maxn][maxn];
int n, m;
void link(int u, int v, int w)
{
    e[++tot] = (Edges){head[u], v, w};
    head[u] = tot;
}
int dfs(int u)
{
    int ans = 0;
    for(int i = head[u]; i; i = e[i].next)
    {
        int v = e[i].to;
        int t = dfs(v);
        ans = ans + t + 1;
        for(int j = std::min(ans, m); j > 0; j--)
        {
            for(int k = std::min(j - 1, ans); k > 0; k--)
            {
                dp[u][j] = std::max(dp[u][j], dp[u][j - k - 1] + dp[v][k] + e[i].weight);
            }
        }
    }
    return ans;
}
int main()
{
    scanf("%d%d", &n, &m);
    for(int i = 1; i < n; i++)
    {
        int u, v, w;
        scanf("%d%d%d", &u, &v, &w);
        link(u, v, w);
    }
    dfs(1);
    printf("%d\n", dp[1][m]);
    return 0;
}

P2286 [HNOI2004]寵物收養場