NOIP2018 保衛王國

2022-03-27 03:10:22 字數 1722 閱讀 1583

題目

強制選點我們可以把那個點權搞成\(-inf\),強制不選我們搞成\(inf\),之後就真的成為動態\(dp\)的板子題了

由於不想像板子那樣再寫乙個最大獨立集的方程,之後利用最小點覆蓋=總點權-最大獨立集的做法,而直接寫了乙個最小點覆蓋的方程,所以寫出了很多鍋

矩陣裡存放相同意義變數的位置可能真實值不相等,於是要取乙個\(min\)

突然發現自己好像也沒有寫出多少鍋,那就這樣吧

**

#include#include#include#include#include#define mp std::make_pair

#define ll long long

#define re register

#define maxn 100005

inline int read()

const ll inf=5e15;

const ll inf=5e10;

typedef std::pairpii;

std::mapma;

char opt[6];

struct ee[maxn<<1];

struct matd[maxn*4];

int n,m,num,__;

int l[maxn*4],r[maxn*4];

int sum[maxn],son[maxn],deep[maxn],head[maxn],top[maxn],bot[maxn];

ll dp[maxn][2],f[maxn][2];int dfn[maxn],id[maxn],pos[maxn],fa[maxn],a[maxn];

inline ll min(ll a,ll b)

inline void add(int x,int y)

inline mat operator*(mat a,mat b)

void dfs1(int x)

}int dfs2(int x,int topf)

return bot[x];

}inline void pushup(int i)

void build(int x,int y,int i)

mat query(int x,int y,int i)

inline void updata(int i,mat val) }

inline void change(int x,ll val)

}signed main()

deep[1]=1,dfs1(1),dfs2(1,1),build(1,n,1);

while(m--)

if(deep[x]>deep[y]) std::swap(x,y),std::swap(a,b);

if(a) change(x,-1ll*inf+a[x]);

else change(x,inf+a[x]);

if(b) change(y,-1ll*inf+a[y]);

else change(y,inf+a[y]);

mat now=query(1,dfn[bot[1]],1);

ll ans=min(now.a[0][1],now.a[1][1]);

if(a) ans+=inf;

if(b) ans+=inf;

printf("%lld\n",ans);

change(y,a[y]);change(x,a[x]);

}return 0;

}

NOIP2018 保衛王國

給定一棵樹,求它的最小點權覆蓋集,其中允許強制某個點選或不選 ddp用lct維護 明確乙個關係式 最小點權覆蓋集 全集 最大點權獨立集 那麼n 2000的暴力就很簡單了,暴力修改,然後求最大點權獨立集就好了 我在考場上就是這麼寫的 關於正解,我採用的是動態dp 動態dp的題解點這裡 根據上面的式子,...

NOIP2018 保衛王國(動態DP)

求最小權值點覆蓋。m mm次詢問,每次給出兩個點,分別要求每個點必須選或必須不選,輸出每次的最小權值覆蓋或者無解輸出 1 1 1強制選或者不選可以看做修改權值為 pm infin 那麼就是這道板題了。include using namespace std typedef long long ll t...

NOIP2018 保衛王國 動態DP

給出一棵樹,有m組詢問,每次詢問給出兩個點,規定他們必須選或必須不選。求樹的最小權覆蓋集。此題有倍增 樹形dp的做法,常數非常優秀,但思路比較難想到。顯然最小權覆蓋集 總點權和 最大權獨立集 看到最大權獨立集,我們想到板子題 luogup4719 模板 動態dp.考慮如何處理詢問。由於我們要權值最小...