Wannafly挑战赛1 C MMSet2

题目链接: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 }
View Code

 

posted @ 2017-10-24 20:37  bin_gege  阅读(355)  评论(0编辑  收藏  举报