題目
強制選點我們可以把那個點權搞成\(-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.考慮如何處理詢問。由於我們要權值最小...