JSOI2018 潛入行動

2022-03-27 02:05:46 字數 1656 閱讀 7332

題目

我好菜啊,嚶嚶嚶

原來本地訪問陣列負下標不會報\(re\)或者\(wa\),甚至能跑出正解啊

這道題還是非常呆的

我們發現\(k\)很小,於是斷定這是乙個樹上揹包

發現在乙個點上安裝控制器並不能控制這個點,可能需要到父親那邊才能控制這個點,於是我們設\(dp[i][j][0/1][0/1]\)表示在以\(i\)為根的子樹裡放置了\(j\)個監視器,控制了除了點\(i\)以外的點,在\(i\)點裝沒裝控制器,\(i\)點有沒有被控制

大力分類套論幾個轉移

\(dp[i][j][0][0]\)因為沒有放監視器,必須要求其兒子們在他們的子樹內部就被監視了,同時因為\(i\)還沒有被監視,於是兒子不能放監視器,於是從\([0][1]\)轉移

\(dp[i][j][1][0]\)因為放了監視器,能監視兒子,於是兒子們有沒有被監視都可以,但是都不能放監視器,於是從\([0][1]\)和\([0][0]\)轉移

\(dp[i][j][0][1]\)因為沒有放監視器,兒子們必須全部被監視到從\([0][1]\)轉移,因為\(i\)被監視,所以至少得有乙個兒子放監視器,所以至少乙個從\([1][1]\)轉移

\(dp[i][j][1][1]\)放了監視器,而要求被監視,從四種狀態都能轉移,但是要求至少有乙個轉移是\([1][0]\)或\([1][1]\)(放了監視器)

直接樹形揹包轉移,之後大力容斥掉沒有選擇那個至少要選擇的情況就好了

發現\(dp[i][j][0][1]\)要減掉的正好是\(dp[i][j][0][0]\),\(dp[i][j][1][1]\)要減掉的正好是\(dp[i][j][1][0]\)

**

#include#include#include#include#define re register

#define ll long long

#define max(a,b) ((a)>(b)?(a):(b))

#define min(a,b) ((a)<(b)?(a):(b))

const int maxn=1e5+5;

const int mod=1e9+7;

inline int read()

struct ee[maxn<<1];

int head[maxn],sum[maxn];

int dp[maxn][105][2][2];

int f[105][2][2];

int n,m,num;

inline void add(int x,int y)

inline int qm(int a)

void dfs(int x,int fa)

continue;

} for(re int j=u;j>=0;--j)

for(re int j=u;j>=0;--j)

for(re int k=0;k<=min(sum[v],m);k++)

} if(!cur)

for(re int j=0;j<=min(sum[x],m);j++)

dp[x][j][0][1]=(dp[x][j][0][1]-dp[x][j][0][0]+mod)%mod,

dp[x][j][1][1]=(dp[x][j][1][1]-dp[x][j][1][0]+mod)%mod;

}int main()

JSOI2018 潛入行動

一棵 n n le10 5 個結點的樹,在一些點上安裝 k k le min n,100 個裝置。每個裝置可以控制所有與安裝位置相鄰的結點 不包括本身 每個點可以安裝至多乙個裝置。問有多少種方案恰好用完 k 個裝置,使得所有的結點都被控制。樹形dp。f i j 0 1 0 1 表示以 i 為根的子樹...

JSOI2018 潛入行動

題目鏈結 參考題解 注意題面 在當前節點設定監聽裝置不能監聽到節點本身。那麼節點能否被覆蓋和節點是否設定監聽裝置需要分開設。設 f 表示以第 i 個節點為根的子樹,除了 i 以外的節點都已經被覆蓋,i 號節點有沒有設定監聽裝置 有沒有被覆蓋的方案數。轉移方程 f sum f f f sum f f ...

JSOI2018 潛入行動

一道思路不難但是寫起來很麻煩的樹形揹包 我們發現每個節點有很多資訊需要保留 所以就暴力的設 f u j 0 1 0 1 表示點u的子樹分配了j個監察器,點u有沒有被控制,點u放沒放監察器 然後就分四種情況暴力討論就好了 注意揹包的時候要卡常數 include include include incl...