Wannafly挑战赛1 C MMSet2
题意:
中文不解释。
题解:
比赛的时候是用的lca+贪心。
今天学了学虚树,这题实际就是求一个虚树的直径。
1 #include<bits/stdc++.h> 2 #define F(i,a,b) for(int i=(a);i<=(b);++i) 3 #define mst(a,b) memset(a,b,sizeof(a)) 4 using namespace std; 5 typedef pair<int,int>P; 6 7 const int N=3e5+7; 8 int in[N],out[N],ti,Dep[N]; 9 namespace LCA 10 { 11 int g[N],v[N*2],nxt[N*2],ed,f[20][N*2]; 12 int idx[N],dep[N*2],vs[N*2],dfn; 13 void init(int n){ed=0,dfn=1;F(i,0,n)g[i]=0;} 14 void adg(int x,int y){v[++ed]=y,nxt[ed]=g[x],g[x]=ed;} 15 void dfs(int u=1,int fa=0,int d=0) 16 { 17 in[u]=++ti,Dep[u]=d; 18 idx[u]=dfn,vs[dfn]=u,dep[dfn++]=d; 19 for(int i=g[u];i;i=nxt[i])if(v[i]!=fa) 20 dfs(v[i],u,d+1),vs[dfn]=u,dep[dfn++]=d; 21 out[u]=ti; 22 } 23 void lca_init(int rt) 24 { 25 dfs(rt);F(i,1,dfn-1)f[0][i]=i; 26 for(int i=1;(1<<i)<dfn;++i) 27 for(int j=1;j+(1<<i)-1<dfn;++j) 28 { 29 int a=f[i-1][j],b=f[i-1][j+(1<<(i-1))]; 30 f[i][j]=dep[a]<=dep[b]?a:b; 31 } 32 } 33 int lca(int x,int y) 34 { 35 x=idx[x],y=idx[y]; 36 if(x>y)x^=y,y^=x,x^=y; 37 int k=31-__builtin_clz(y-x+1); 38 int a=f[k][x],b=f[k][y-(1<<k)+1]; 39 return vs[dep[a]<=dep[b]?a:b]; 40 } 41 } 42 43 44 namespace vtree 45 { 46 int q[N],t,tot,x;bool vis[N],vip[N];vector<P>G[N]; 47 void clear(int *a,int tot){F(i,1,tot)vis[a[i]]=vip[a[i]]=0,G[a[i]].clear();} 48 bool cmp(int x,int y){return in[x]<in[y];} 49 void addedge(int x,int y) 50 { 51 G[x].push_back(P(y,Dep[y]-Dep[x])); 52 G[y].push_back(P(x,Dep[y]-Dep[x])); 53 } 54 //构建m个点的虚树,用完记得clear(a,tot),注意特判1号节点。 55 int build(int *a,int m) 56 { 57 F(i,1,m)vis[a[i]]=vip[a[i]]=1; 58 if(!vis[1])a[++m]=1; 59 sort(a+1,a+1+m,cmp),tot=m; 60 F(i,2,m)if((x=LCA::lca(a[i-1],a[i]))!=1&&!vis[x])vis[a[++tot]=x]=1; 61 sort(a+1,a+1+tot,cmp),q[t=1]=1; 62 F(i,2,tot) 63 { 64 while(in[a[i]]<in[q[t]]||out[a[i]]>out[q[t]])t--; 65 addedge(q[t],a[i]),q[++t]=a[i]; 66 } 67 return tot; 68 } 69 } 70 71 int n,m,x,y,num,a[N],mx[N]; 72 73 void dfs(int x,int fa,int val) 74 { 75 mx[x]=val; 76 for(auto &it:vtree::G[x]) 77 if(it.first!=fa) 78 dfs(it.first,x,val+it.second); 79 } 80 81 int main(){ 82 scanf("%d",&n); 83 F(i,2,n) 84 { 85 scanf("%d%d",&x,&y); 86 LCA::adg(x,y),LCA::adg(y,x); 87 } 88 LCA::lca_init(1),scanf("%d",&m); 89 F(i,1,m) 90 { 91 scanf("%d",&num); 92 F(j,1,num)scanf("%d",a+j); 93 num=vtree::build(a,num); 94 dfs(1,0,0); 95 int now,v=-1; 96 F(j,1,num)if(mx[a[j]]>v)now=a[j],v=mx[a[j]]; 97 dfs(now,0,0),v=-1; 98 F(j,1,num)if(vtree::vis[a[j]]) 99 { 100 if(mx[a[j]]>v)v=mx[a[j]]; 101 } 102 printf("%d\n",(v+1)/2); 103 vtree::clear(a,num); 104 } 105 return 0; 106 }