虚树+树形DP
本题100W的点数……不用虚树真的好吗……
Orz ZYF
我的感悟:
dp的过程跟SPOJ 1825 FTOUR2 的做法类似,依次枚举每个子树,从当前子树和之前的部分中各找一条最长(短)路径更新答案,再把这个子树的最短路径加入到x节点中去(之前算过的部分)这样就实现了枚举所有可能的最优情况!而且复杂度很低!避免了两两之间的枚举……
1 /************************************************************** 2 Problem: 3611 3 User: Tunix 4 Language: C++ 5 Result: Accepted 6 Time:7460 ms 7 Memory:181024 kb 8 ****************************************************************/ 9 10 //BZOJ 3611 11 #include<cstdio> 12 #include<cstring> 13 #include<cstdlib> 14 #include<iostream> 15 #include<algorithm> 16 #define rep(i,n) for(int i=0;i<n;++i) 17 #define F(i,j,n) for(int i=j;i<=n;++i) 18 #define D(i,j,n) for(int i=j;i>=n;--i) 19 using namespace std; 20 int getint(){ 21 int v=0,sign=1; char ch=getchar(); 22 while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)sign=-1;ch=getchar();} 23 while(ch>=‘0‘&&ch<=‘9‘){ v=v*10+ch-‘0‘; ch=getchar();} 24 return v*=sign; 25 } 26 /******************tamplate*********************/ 27 const int N=1000086,INF=~0u>>2; 28 typedef long long LL; 29 30 int n,m,dfn[N],dfs_clock,dep[N],fa[N][21],a[N]; 31 LL ans,g[N]; 32 int f[N],_min[N],_max[N],ans1,ans2; 33 bool v[N]; 34 35 inline int LCA(int x,int y){ 36 if(dep[x]<dep[y]) swap(x,y); 37 int t=dep[x]-dep[y]; 38 F(i,0,20) if(t&(1<<i)) x=fa[x][i]; 39 if (x==y) return x; 40 D(i,20,0) if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i]; 41 return fa[x][0]; 42 } 43 struct graph{ 44 int head[N],to[N<<1],next[N<<1],len[N<<1],cnt; 45 void add(int x,int y){ 46 to[++cnt]=y; next[cnt]=head[x]; head[x]=cnt; 47 to[++cnt]=x; next[cnt]=head[y]; head[y]=cnt; 48 } 49 void ad(int x,int y){ 50 to[++cnt]=y; next[cnt]=head[x]; head[x]=cnt; len[cnt]=dep[y]-dep[x]; 51 } 52 void dfs(int x){ 53 dfn[x]=++dfs_clock; 54 F(i,1,20) if(dep[x]>=(1<<i)) fa[x][i]=fa[fa[x][i-1]][i-1]; else break; 55 for(int i=head[x];i;i=next[i]) 56 if(to[i]!=fa[x][0]){ 57 fa[to[i]][0]=x; 58 dep[to[i]]=dep[x]+1; 59 dfs(to[i]); 60 } 61 } 62 void DP(int x){ 63 f[x]=v[x]; g[x]=0; 64 _min[x]=v[x] ? 0 : INF; 65 _max[x]=v[x] ? 0 : -INF; 66 for(int i=head[x];i;i=next[i]){ 67 int y=to[i]; 68 DP(y); 69 ans+=(g[x]+f[x]*len[i])*f[y]+g[y]*f[x]; 70 f[x]+=f[y]; 71 g[x]+=g[y]+(LL)len[i]*f[y]; 72 ans1=min(ans1,_min[x]+_min[y]+len[i]); 73 ans2=max(ans2,_max[x]+_max[y]+len[i]); 74 _min[x]=min(_min[x],_min[y]+len[i]); 75 _max[x]=max(_max[x],_max[y]+len[i]); 76 } 77 head[x]=0; 78 } 79 }G1,G2; 80 inline bool cmp(int a,int b){ return dfn[a]<dfn[b]; } 81 int st[N],top; 82 int main(){ 83 // freopen("3611.in","r",stdin); 84 n=getint(); 85 int x,y; 86 F(i,2,n){ 87 x=getint(); y=getint(); 88 G1.add(x,y); 89 } 90 G1.dfs(1); 91 92 int T=getint(); 93 while(T--){ 94 m=getint(); 95 F(i,1,m) {a[i]=getint(); v[a[i]]=1;} 96 sort(a+1,a+m+1,cmp); 97 98 st[top=1]=1; G2.cnt=0; 99 ans=0; ans1=INF; ans2=-INF; 100 F(i,1,m){ 101 int x=a[i],f=LCA(x,st[top]); 102 while(dep[f]<dep[st[top]]){ 103 if(dep[f]>=dep[st[top-1]]){ 104 G2.ad(f,st[top--]); 105 if(st[top]!=f) st[++top]=f; 106 break; 107 } 108 G2.ad(st[top-1],st[top]); top--; 109 } 110 if(st[top]!=x) st[++top]=x; 111 } 112 while(--top) G2.ad(st[top],st[top+1]); 113 G2.DP(1); 114 printf("%lld %d %d\n",ans,ans1,ans2); 115 F(i,1,m) v[a[i]]=0; 116 } 117 return 0; 118 }
时间: 2024-12-17 19:45:43