對於這個題目,我的做法是換根dp, 因為可以選擇將某乙個點染成白色(不論之前的點是黑是白) , 做法如下:
將每個點當成根節點, 然後將根節點染成白色, 完全符合題意;;
首先dfs一下, 自底向上,求出每乙個點在子樹內的白色連通塊大小。
然後從上到下開始算對孩子節點的貢獻::
如果當前點是黑色, 那麼對兒子節點肯定沒有貢獻 , 因為上面的所有節點都被這個黑色節點隔開了,下面的節點不能和上面的節點連線;
如果當前節點是白色 :
如果孩子節點是黑色, 那麼在第一次dfs的時候,孩子節點肯定對這個父親節點沒有貢獻, 那麼就當前節點對孩子節點直接傳遞下去dp[u]
如果孩子節點是白色, 那麼在第一次dfs的時候,孩子節點肯定對這個父親節點有貢獻, 那麼當前節點對孩子節點的貢獻就是dp[u] - dp[x] ,剪掉孩子的貢獻, 避免重複計算
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#pragma gcc optimize(3 , "ofast" , "inline")
using
namespace std ;
typedef
long
long ll ;
const
double esp =
1e-6
, pi =
acos(-
1);typedef pair<
int,
int> pii ;
const
int n =
1e6+
10, inf =
0x3f3f3f3f
, mod =
1e9+7;
intin()
while
(isdigit
(ch)
) x = x *
10+ ch -
48, ch =
getchar()
;return x * f ;
}int col[n]
, dp[n]
, n ;
vector<
int> v[n]
;void
dfs(
int u ,
int f)
return;}
int ans =0;
void
dfs1
(int u ,
int f ,
int sum)
}int
main()
dfs(1,
0);dfs1(1
,0,0
);cout << ans << endl ;
return0;
}/*13wbwwbbbbbwwwb
1 21 3
2 42 5
3 63 7
5 88 10
8 11
7 99 12
9 13
4*/
藍魔法師 牛客
將一顆 n 1 leq n leq 2000 個結點的樹,分成 t 1 leq t leq n 個連通塊,且每個連通塊的大小都小於或者等於 k 1 leq k leq 2000 求劃分方案數?dp i j 以 i 為根的子樹向父親結點 u 提供 j 個點的貢獻 dp fa i cnt 1 cnt 2...
牛客小白月賽25
分情況討論 include using namespace std const int n 2e5 5 typedef long long ll int a n int main void if n x else printf lld n ans return0 用字元陣列來模擬棧 include ...
牛客Wannafly挑戰賽27 A 灰魔法師
感謝大佬 講解非常仔細 做題的時候也有想過去打表,然後就沒有了,還是沒有找到其中的規律。這裡補一條完全平方數的定義?這個數開根號後是整數如 9,25,36 因為題目資料是1e5,所以兩個數相加也只有2e5,從1到2e5滿足條件的完全平方數個數也只有400 就用乙個陣列去記錄下來,然後for迴圈把給出...