1. 程式人生 > >BZOJ4871 Shoi2017摧毀“樹狀圖”(樹形dp)

BZOJ4871 Shoi2017摧毀“樹狀圖”(樹形dp)

  設f[i][0/1/2/3/4/5]表示i子樹中選一條鏈不包含根/i子樹中選一條鏈包含根但不能繼續向上延伸/i子樹中選一條鏈可以繼續向上延伸/選兩條鏈不包含根/選兩條鏈包含根但不能繼續向上延伸/選兩條鏈能繼續向上延伸,大力討論即可。程式碼看起來很(mo)有(ming)意(qi)思(miao)。

#include<iostream> 
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace
std; #define ll long long #define N 500010 char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;} int gcd(int n,int m){return m==0?n:gcd(m,n%m);} int read() { int x=0,f=1;char c=getchar(); while (c<'0'||c>'9
') {if (c=='-') f=-1;c=getchar();} while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } int T,n,p[N],f[N][6],t; int mx[4][6]; struct data{int to,nxt; }edge[N<<1]; void addedge(int x,int y){t++;edge[t].to=y,edge[t].nxt=p[x],p[x]=t;} inline void
up(int &x,int y){x=max(x,y);} inline int max(int x,int y,int z){return max(max(x,y),z);} void update(int x) { for (int i=0;i<6;i++) for (int j=0;j<4;j++) if (f[x][i]>f[mx[j][i]][i]) { for (int k=3;k>j;k--) mx[k][i]=mx[k-1][i]; mx[j][i]=x;break; } } int findmx(int x){return f[mx[0][x]][x];} int findmx(int x,int y) { if (mx[0][x]!=mx[0][y]) return f[mx[0][x]][x]+f[mx[0][y]][y]; return max(f[mx[0][x]][x]+f[mx[1][y]][y],f[mx[1][x]][x]+f[mx[0][y]][y]); } int findmx(int x,int y,int z) { int s=-n; for (int i=0;i<4;i++) for (int j=i+1;j<4;j++) for (int k=0;k<4;k++) if (mx[k][z]!=mx[i][x]&&mx[k][z]!=mx[j][y]) up(s,f[mx[k][z]][z]+f[mx[i][x]][x]+f[mx[j][y]][y]); return s; } int findmx(int a,int b,int c,int d){return f[mx[0][a]][a]+f[mx[1][b]][b]+f[mx[2][c]][c]+f[mx[3][d]][d];} void dfs(int k,int from) { int son=0; for (int i=p[k];i;i=edge[i].nxt) if (edge[i].to!=from) son++,dfs(edge[i].to,k); memset(mx,0,sizeof(mx)); for (int i=p[k];i;i=edge[i].nxt) if (edge[i].to!=from) update(edge[i].to); f[k][0]=max(findmx(0),findmx(1)+1,findmx(2)+1); f[k][1]=findmx(2,2)+son-2; f[k][2]=max(son,findmx(2)+son-1); f[k][3]=max(findmx(3),findmx(4)+1,findmx(5)+1); for (int i=0;i<3;i++) for (int j=i;j<3;j++) up(f[k][3],findmx(i,j)+1-(i==0)-(j==0)); f[k][4]=max(findmx(2,2,2,2)-4,max(findmx(2,2,0)-3,findmx(2,2,1)-3),findmx(2,5)-2)+son; f[k][5]=max(max(findmx(5)-1,findmx(2,2,2)-3,max(findmx(2,2),findmx(2,1),findmx(2,0))-2),max(findmx(0),findmx(1),findmx(2))-1)+son; } int main() { #ifndef ONLINE_JUDGE freopen("bzoj4871.in","r",stdin); freopen("bzoj4871.out","w",stdout); const char LL[]="%I64d\n"; #else const char LL[]="%lld\n"; #endif T=read();int op=read(); while (T--) { n=read();if (op>=1) read(),read();if (op==2) read(),read(); t=0;for (int i=1;i<=n;i++) p[i]=0; f[0][0]=f[0][1]=f[0][2]=f[0][3]=f[0][4]=f[0][5]=-n; for (int i=1;i<n;i++) { int x=read(),y=read(); addedge(x,y),addedge(y,x); } dfs(1,1); printf("%d\n",max(max(f[1][0],f[1][1],f[1][2]),max(f[1][3],f[1][4],f[1][5]))); } return 0; }