洛谷 P2996 [USACO10NOV]拜訪奶牛Visiting Cows

P2996

傳送門node

題意:

給你一棵樹,每一條邊上最多選一個點,問你選的點數.c++

個人思想:

一開始我是想用黑白點染色的思想來作,就是每一條邊都選擇一個點.git

能夠跑兩邊一遍在乎的時候染成黑,第二遍染成白,取一個最大值.spa

就能夠獲得\(30\)分的高分.code

#include <bits/stdc++.h>
#define N 100010
#define M 1010
#define _ 0

using namespace std;
int n, tot, ans, add_edge, color[N], head[N];
struct node {
    int next, to;
}edge[N];

int read() {
    int s = 0, f = 0; char ch = getchar();
    while (!isdigit(ch)) f |= (ch == '-'), ch = getchar();
    while (isdigit(ch)) s = s * 10 + (ch ^ 48), ch = getchar();
    return f ? -s : s;
}

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

void dfs(int x, int fx) {
    if (color[fx] == 0) {
        color[x] = 1;
        tot++;
    }
    for (int i = head[x]; i; i = edge[i].next) {
        int to = edge[i].to;
        if (to == fx) continue;
        dfs(to, x);
    }
}

int main() {
    n = read();
    int point;
    for (int i = 1, x, y; i < n; i++) {
        x = read(), y = read();
        add(x, y), add(y, x);
        point = x;
    }
    dfs(point, 0);
    ans = max(ans, tot);
    memset(color, 0, sizeof (color));
    tot = 0, color[0] = 1;
    dfs(point, 0);
    cout << max(ans, tot);
}

很明顯這樣作是錯誤的.來看這樣一組樣例.

按照上述方法跑出來就是\(5\),顯然答案是\(7\).而後我就是這樣被學長\(hack\)了.blog

而後就問了學長樹形\(DP\).get

正確思路:

咱們設\(dp[i][1/0]\)來表示\(i\)\(i\)的子樹在\(i\),選仍是不選,時的最大權值.it

而後又由於在\(dp[i][1]\)時他的子節點不能選\(dp[to][1]\).class

\(dp[i][0]\)時均可以選.咱們就能夠獲得這樣的轉移方程(用\(to\)來表示\(i\)的子節點):hack

\[dp[x][0] += max(dp[to][1], dp[to][0]);\]
\[ dp[x][1] += dp[to][0]; \]

而後就作完了.

code :

#include <bits/stdc++.h>
#define N 100010
#define M 50010
#define _ 0

using namespace std;
int n, add_edge, head[N];
int dp[M][2];
struct node {
    int next, to;
}edge[N];

int read() {
    int s = 0, f = 0; char ch = getchar();
    while (!isdigit(ch)) f |= (ch == '-'), ch = getchar();
    while (isdigit(ch)) s = s * 10 + (ch ^ 48), ch = getchar();
    return f ? -s : s;
}

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

void dfs(int x, int fx) {
    dp[x][1] = 1;
    for (int i = head[x]; i; i = edge[i].next) {
        int to = edge[i].to;
        if (to == fx) continue;
        dfs(to, x);
        dp[x][0] += max(dp[to][1], dp[to][0]);
        dp[x][1] += dp[to][0];
    }
}

int main() {
    n = read();
    for (int i = 1, x, y; i < n; i++) {
        x = read(), y = read();
        add(x, y), add(y, x);
    }
    dfs(1, 0); 
    cout << max(dp[1][0], dp[1][1]);
}
相關文章
相關標籤/搜索