1. 程式人生 > >BZOJ5314:[JSOI2018]潛入行動——題解

BZOJ5314:[JSOI2018]潛入行動——題解

地球 return 活動 必須 line block def sdi type

https://www.lydsy.com/JudgeOnline/problem.php?id=5314

https://www.luogu.org/problemnew/show/P4516

https://loj.ac/problem/2546

外星人又雙叒叕要攻打地球了,外星母艦已經向地球航行!這一次,JYY已經聯系好了黃金艦隊,打算聯合所有JSOIer抵禦外星人的進攻。在黃金艦隊就位之前,JYY打算事先了解外星人的進攻計劃。現在,攜帶了監聽設備的特工已經秘密潛入了外星人的母艦,準備對外星人的通信實施監聽。外星人的母艦可以看成是一棵n個節點、n-1條邊的無向樹,樹上的節點用1,2...n編號。JYY的特工已經裝備了隱形模塊,可以在外星人母艦中不受限制地活動,可以神不知鬼不覺地在節點上安裝監聽設備。如果在節點u安裝監聽設備,則JYY能夠監聽與u直接相鄰所有的節點的通信。換言之,如果在節點u安裝監聽設備,則對於樹中每一條邊(u,v),節點v都會被監聽。特別註意放置在節點u的監聽設備並不監聽u本身的通信,這是JYY特別為了防止外星人察覺部署的戰術。
JYY的特工一共攜帶了k個監聽設備,現在JYY想知道,有多少種不同的放置監聽設備的方法,能夠使得母艦上所有節點的通信都被監聽?為了避免浪費,每個節點至多只能安裝一個監聽設備,且監聽設備必須被用完。

一個很好想的dp[i][j][0/1][0/1]表示i為根的子樹放了j個設備,i結點沒放/放了設備,i結點沒被控制/控制。

然後就是驚天地泣鬼神的轉移了,看代碼應該能看懂吧,我們其實就是把每棵子樹按照乘法原理依次加入即可。

難還真不難,但是dp式子真心長,還卡你常,你就沒話說了(雖然最壞復雜度是O(nkk)的但是顯然達不到,而且這種樹形dp依賴每棵子樹更新的話應該是有O(nk)做法的。)

#include<cmath>
#include
<queue> #include<cstdio> #include<cctype> #include<cstring> #include<iostream> #include<algorithm> using namespace std; typedef long long ll; const int p=1e9+7; const int N=1e5+5; const int K=105; inline int read(){ int X=0,w=0;char ch=0; while(!isdigit(ch)){w|=ch==
-;ch=getchar();} while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar(); return w?-X:X; } struct node{ int to,nxt; }e[N*2]; int n,k,cnt,head[N],size[N]; int f[N][K][2][2],g[K][2][2]; inline void ins(int u,int v){ e[++cnt].to=v;e[cnt].nxt=head[u];head[u]=cnt; } inline void add(int &x,ll y){ x+=y%p; if(x>=p)x-=p; } void dfs(int u,int fa){ size[u]=1; f[u][0][0][0]=f[u][1][1][0]=1; for(int i=head[u];i;i=e[i].nxt){ int v=e[i].to; if(v==fa)continue; dfs(v,u); for(int i=0,l1=min(k,size[u]);i<=l1;i++){ g[i][0][0]=f[u][i][0][0];f[u][i][0][0]=0; g[i][0][1]=f[u][i][0][1];f[u][i][0][1]=0; g[i][1][0]=f[u][i][1][0];f[u][i][1][0]=0; g[i][1][1]=f[u][i][1][1];f[u][i][1][1]=0; } for(int i=0,l1=min(k,size[u]);i<=l1;i++){ for(int j=0,l2=min(k-i,size[v]);j<=l2;j++){ add(f[u][i+j][0][0],(ll)g[i][0][0]*f[v][j][0][1]); add(f[u][i+j][0][1],(ll)g[i][0][1]*(f[v][j][0][1]+f[v][j][1][1])+(ll)g[i][0][0]*f[v][j][1][1]); add(f[u][i+j][1][0],(ll)g[i][1][0]*(f[v][j][0][0]+f[v][j][0][1])); add(f[u][i+j][1][1],(ll)g[i][1][1]*((ll)f[v][j][0][0]+f[v][j][0][1]+f[v][j][1][0]+f[v][j][1][1])+(ll)g[i][1][0]*(f[v][j][1][0]+f[v][j][1][1])); } } size[u]+=size[v]; } } int main(){ n=read(),k=read(); for(int i=1;i<n;i++){ int u=read(),v=read(); ins(u,v);ins(v,u); } dfs(1,0); printf("%d\n",(f[1][k][0][1]+f[1][k][1][1])%p); return 0; }

BZOJ5314:[JSOI2018]潛入行動——題解