AcWing 359 創世紀 基環樹,樹形dp

2021-09-27 07:35:01 字數 1681 閱讀 6401

這道題bzoj上也有,可惜我沒許可權,只在acwing上過了

題目:首先是建邊問題,乙個點可不可以選取決於有沒有限制它的點沒有被選上,因此建立邊的方式就是從 被限制的點指向限制它的點,單向邊,此時假如需要選乙個點,那麼必定有乙個以上它的子節點沒有被選

用dp[i][option] 來做dp陣列,其中i為哪乙個點,option為0的話表示不選這個點,option為1的話表示選這個點。

假設to是now的子節點,那麼

不選now這個點,那麼其子節點怎麼選都無所謂,直接都選最大的

假如選now這個點,其子節點就必定有乙個不能被選上,此時如何表達呢?

首先我們先選子節點最大的那個狀態:

假如此時有乙個子節點的dp[to][0]>=dp[to][1],那就符合條件,但是假如所有子節點都是dp[to][1]>dp[to][0]

此時我們需要找到乙個dp[to][1]-dp[to][0] 最小的,然後讓dp[now][1]減去這個最小值即可

其中sto初始化為正無窮,假如有乙個dp[to][0]>=dp[to][1],那麼sto的結果將會是0

最後,對於環形問題,有時候是將它切割成線性問題,然後分類討論完成。

本題就是需要找到環上的乙個點,將它和它限制的那個點斷開,先後進行兩次樹形dp,第一次是假設環上的這個點對其限制的點不起限制作用,另外一次是強制環上那個點已經限制了其可以限制的點(也就是環上那個點不選)

#includeusing namespace std;

const int maxn = 1e5 + 7;

int n, tot, root;

int fat[maxn], dp[maxn][2];

int head[maxn], nxt[maxn << 1], to[maxn << 1];

int vis[maxn];

int flag;

void add_edge(int fro,int to)

void tree_dp(int now)

dp[now][1] = dp[now][0] - sto + 1;

if (now == fat[root] && flag) dp[now][1] = dp[now][0] + 1; //假如起強制限制作用,那麼那個點的其他子節點就都可以隨便選了

}int main()

int ans = 0;

for (int i = 1; i <= n; i++)

flag = 0; //flag=0表示不起限制作用

tree_dp(root);

res = max(dp[root][0], dp[root][1]);

flag = 1; //表示起強制限制作用

tree_dp(root);

res = max(res, dp[root][0]);

ans += res;

} cout << ans << endl;

}

NOIP模擬賽 創世紀

好水的題呀 我們根據它邊連得性質,很容易發現它是乙個基環樹。我們對於樹上,只要使得每個節點至少有乙個點不被選就好了,用樹形dp可以解決,分別求出選這個點與不選這個點時的值。而對於環上的部分,我們就找到兩個相鄰的點,跑一邊環用先前的dp值找出環的最大值,加在一起就行了。include include ...

BZOJ 3037 創世紀 樹形DP

題目大意 給定一張有向圖,每個點有且僅有一條出邊,要求若乙個點x扔下去,至少存在乙個保留的點y,y的出邊指向x,求最多扔下去多少個點 首先原題的意思就是支配關係 我們反向考慮 求最少保留的點 要求乙個點若扔出去 則必須存在乙個保留的點指向它 於是這就是最小支配集 不過由於是有向圖 所以乙個點要麼選擇...

NOIP2014模擬11 6 創世紀

這題,我們可以轉化成乙個圖論問題,我們只需要記錄入度個數就好了 首先,然後我們把它刪掉之後,就可以看到,它所能控制的點就合法了,因為它可以被乙個不合法的點控制,並把合法的點的出度刪掉。每次就是這樣做。最後一種gg的情況,要特判一下。就是有環的情況 於是,這樣一題看似很難的題就被化成乙個沒有任何演算法...