HDU 6115 Factory(虚树+根号分治)
Posted On 2019年4月28日
Factory
Solution
对于每个大小\(>size\)的集合\(O(n)\)预处理出其与其他集合的答案,这部分复杂度\(O(\frac{n}{size}\cdot n)\)
对于大小\(<size\)的集合在询问时建虚树\(O(size)\)解决即可,使用\(O(1)\)LCA时这部分复杂度\(O(size\cdot m)\)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 |
#include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #include <bitset> #include <algorithm> #include <vector> #include <tr1/unordered_map> using namespace std; using namespace std::tr1; inline int read() { int f=1,k=0;char c=getchar(); while (c<'0'||c>'9')c=='-'&&(f=-1),c=getchar(); while (c>='0'&&c<='9')k=k*10+c-'0',c=getchar(); return k*f; } const int maxn=400000+100,inf=1e9; int last[maxn],tmp[maxn],cnt[maxn],mn[maxn],upmn[maxn],Last[maxn],stk[maxn],tot,all,used[maxn],n; vector<int>store[maxn],bel[maxn]; unordered_map<int,unordered_map<int,int> >ans; unordered_map<int,unordered_map<int,bool> >vis; pair<int,int>tp[maxn]; struct mc{int too,nxt,val;}e[maxn<<1],E[maxn<<1]; struct HLD { int fa[maxn],top[maxn],dep[maxn],dfn[maxn],Time,mp[maxn],EULER,in[maxn],DEP[maxn],ALL,mn[maxn][20]; void dfs(const int cur) { dfn[cur]=++Time;mp[in[cur]=++EULER]=cur; for (int i=last[cur];i;i=e[i].nxt) if (e[i].too!=fa[cur]) dep[e[i].too]=dep[cur]+e[i].val,fa[e[i].too]=cur,mp[++EULER]=cur,DEP[e[i].too]=DEP[cur]+1, dfs(e[i].too); } inline int main(int a,int b) { int l=in[a],r=in[b]; if (l>r)swap(l,r); int lg=log(r-l+1)/log(2),A=mn[l][lg],B=mn[r-(1<<lg)+1][lg]; return DEP[A]<DEP[B]?A:B; } inline void pre() { EULER=Time=0; dfs(1); ALL=log(EULER)/log(2); for (int i=1;i<=EULER;i++)mn[i][0]=mp[i]; for (int j=1;j<=ALL;j++) for (int i=1;i+(1<<j)-1<=EULER;i++) { int a=mn[i][j-1],b=mn[i+(1<<j-1)][j-1]; if (DEP[a]<DEP[b])mn[i][j]=a; else mn[i][j]=b; } } inline int getdis(const int a,const int b,int lca=0) { if (!lca)lca=main(a,b); return dep[a]+dep[b]-dep[lca]*2; } }LCA; void dfs(int*last,mc*e,const int cur,const int fa) { for (int i=last[cur];i;i=e[i].nxt) if (e[i].too!=fa)dfs(last,e,e[i].too,cur),mn[cur]=min(mn[cur],mn[e[i].too]+e[i].val); } void getup(int*last,mc*e,const int cur,const int fa) { for (int i=last[cur];i;i=e[i].nxt) if (e[i].too!=fa)mn[e[i].too]=min(mn[e[i].too],mn[cur]+e[i].val),getup(last,e,e[i].too,cur); } inline void add(const int a,const int b,const int c) { used[++all]=a;used[++all]=b; E[++tot]=(mc){b,Last[a],c};Last[a]=tot; E[++tot]=(mc){a,Last[b],c};Last[b]=tot; } inline void work() { n=read();int m=read(),lg2=log(n)/log(2),siz=sqrt(n);siz/=10; memset(last,0,sizeof(int)*(n+1)); for (int i=1;i<n;i++) { int a=read(),b=read(); e[i<<1].too=b,e[i<<1].nxt=last[a],last[a]=i<<1; e[i<<1|1].too=a,e[i<<1|1].nxt=last[b],last[b]=i<<1|1; e[i<<1].val=e[i<<1|1].val=read(); } LCA.pre(); for (int i=1;i<=m;i++) { int N=read(); for (int j=1;j<=N;j++)tmp[j]=read(); sort(tmp+1,tmp+1+N); N=unique(tmp+1,tmp+1+N)-tmp-1; cnt[i]=N; for (int j=1;j<=N;j++)store[i].push_back(tmp[j]),bel[tmp[j]].push_back(i); } for (int i=1;i<=m;i++) if (cnt[i]>=siz) { memset(mn,0x3f,sizeof(int)*(n+1)); for (int j=0;j<store[i].size();j++) mn[store[i][j]]=0; dfs(last,e,1,1); getup(last,e,1,1); for (int j=1;j<=n;j++) { int dis=mn[j]; for (int k=0;k<bel[j].size();k++) { int cur=bel[j][k]; if (!vis[cur][i])ans[cur][i]=ans[i][cur]=dis,vis[cur][i]=vis[i][cur]=1; else ans[cur][i]=ans[i][cur]=min(ans[cur][i],dis); } } } memset(mn,0x3f,sizeof(mn)); for (int Q=read();Q;Q--) { int a=read(),b=read(); if (cnt[a]>=siz||cnt[b]>=siz)printf("%d\n",ans[a][b]); else { int cnt=0,top=0;tot=0;all=0; for (int i=0,now;i<store[a].size();i++)now=store[a][i],tp[++cnt]=make_pair(LCA.dfn[now],now); for (int i=0,now;i<store[b].size();i++)now=store[b][i],tp[++cnt]=make_pair(LCA.dfn[now],now); sort(tp+1,tp+1+cnt); cnt=unique(tp+1,tp+1+cnt)-tp-1; stk[++top]=1; for (int i=1;i<=cnt;i++) { int now=tp[i].second; if (now==1)continue; if (top<=1)stk[++top]=tp[i].second; else { int lca=LCA.main(now,stk[top]); if (lca==stk[top])stk[++top]=now; else { while (top>1&&LCA.dfn[lca]<=LCA.dfn[stk[top-1]]) add(stk[top],stk[top-1],LCA.getdis(stk[top],stk[top-1])),--top; if (lca!=stk[top])add(stk[top],lca,LCA.getdis(lca,stk[top])),stk[top]=lca; stk[++top]=now; } } } for (int i=top;i>1;i--)add(stk[i],stk[i-1],LCA.getdis(stk[i],stk[i-1])); for (int i=1;i<=all;i++)mn[used[i]]=inf; for (int i=0;i<store[a].size();i++) mn[store[a][i]]=0; dfs(Last,E,1,1); getup(Last,E,1,1); int aw=inf; for (int i=0;i<store[b].size();i++) aw=min(aw,mn[store[b][i]]); printf("%d\n",aw); for (int i=1;i<=all;i++)Last[used[i]]=0; } } for (int i=1;i<=n;i++)store[i].clear(),ans[i].clear(),bel[i].clear(),vis[i].clear(); } signed main() { for (int T=read();T;T--)work(); } |
Subscribe
0 评论