[最短路 虚树+线段树优化建图] BZOJ 4912 [Sdoi2017]天才黑客
2017-06-09 14:51
477 查看
sro clrs97老师:”T1特别好写” orz
听说SPFA被卡了 /点蜡
这个东西跑最短路,状态肯定不能指记录点,还要记录是哪条边走过来的,那干脆就直接记录边
把边变成点,把点变成连在边之间的边
我是把一条边拆成两个点,中间设为边的费用
lcp的费用在点变成的边上,这个东西裸的连,在原图一个点上是O(deg2)的肯定炸
那么就建一颗虚树,然后枚举lca,把lca是这个的点两两之间都连边为这个lca的深度,这个可以枚举lca的一个儿子,这个儿子子树中所有点向其他儿子子树中所有点连边,这个可以dfs序加线段树优化下
然后就好了... 我写了 6KB
听说SPFA被卡了 /点蜡
这个东西跑最短路,状态肯定不能指记录点,还要记录是哪条边走过来的,那干脆就直接记录边
把边变成点,把点变成连在边之间的边
我是把一条边拆成两个点,中间设为边的费用
lcp的费用在点变成的边上,这个东西裸的连,在原图一个点上是O(deg2)的肯定炸
那么就建一颗虚树,然后枚举lca,把lca是这个的点两两之间都连边为这个lca的深度,这个可以枚举lca的一个儿子,这个儿子子树中所有点向其他儿子子树中所有点连边,这个可以dfs序加线段树优化下
然后就好了... 我写了 6KB
#include<cstdio> #include<cstdlib> #include<algorithm> #include<cstring> #include<queue> #include<vector> #define pb push_back #define cl(x) memset(x,0,sizeof(x)) using namespace std; typedef long long ll; typedef pair<ll,int> abcd; inline char nc(){ static char buf[100000],*p1=buf,*p2=buf; return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++; } inline void read(int &x){ char c=nc(),b=1; for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1; for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b; } inline void print(ll x){ if (x>=10) print(x/10); putchar('0'+x%10); } const int N=100005; vector<int> ind ,outd ; #define V G[p].v namespace S{ //SAAP const int N=2000005; const int M=4000005; struct edge{ int u,v,w,next; }G[M<<1]; int head ,inum; inline void add(int u,int v,int w){ int p=++inum; G[p].u=u; G[p].v=v; G[p].w=w; G[p].next=head[u]; head[u]=p; } inline void clear(){ cl(head); inum=0; } ll dis ; priority_queue<abcd> Q; inline void Dij(int ncnt){ while (!Q.empty()) Q.pop(); for (int i=1;i<=ncnt;i++) dis[i]=1LL<<60; for (int i=0;i<(int)outd[1].size();i++) dis[outd[1][i]]=0,Q.push(abcd(0,outd[1][i])); while (!Q.empty()){ int u=Q.top().second; ll d=Q.top().first; Q.pop(); if (dis[u]!=-d) continue; for (int p=head[u];p;p=G[p].next) if (dis[V]>dis[u]+G[p].w){ dis[V]=dis[u]+G[p].w; Q.push(abcd(-dis[V],V)); } } } } struct edge{ int u,v,next; }G[N<<1]; int head ,inum; inline void add(int u,int v,int p){ G[p].u=u; G[p].v=v; G[p].next=head[u]; head[u]=p; } const int KK=18; int fat [KK],depth ; int pre ,clk; inline void dfs(int u,int fa){ fat[u][0]=fa; depth[u]=depth[fa]+1; pre[u]=++clk; for (int k=1;k<KK;k++) fat[u][k]=fat[fat[u][k-1]][k-1]; for (int p=head[u];p;p=G[p].next) if (V!=fa) dfs(V,u); } inline int LCA(int u,int v){ if (depth[u]<depth[v]) swap(u,v); for (int k=KK-1;~k;k--) if ((depth[u]-depth[v])>>k&1) u=fat[u][k]; if (u==v) return u; for (int k=KK-1;~k;k--) if (fat[u][k]!=fat[v][k]) u=fat[u][k],v=fat[v][k]; return fat[u][0]; } int n,m,K; int iu ,iv ,w ,pos ; int ncnt; namespace XS{ const int N=2000005; struct edge{ int u,v,next; }G ; int head ,inum; int vst ,Clk; inline int &Head(int u){ return vst[u]!=Clk?vst[u]=Clk,head[u]=0:head[u]; } inline void add(int u,int v){ int p=++inum; G[p].u=u; G[p].v=v; G[p].next=Head(u); Head(u)=p; } int pre ,clk,back ; int size ; inline void dfs(int u){ pre[u]=++clk; back[clk]=u; size[u]=1; for (int p=Head(u);p;p=G[p].next) dfs(V),size[u]+=size[V]; } int lrt,rrt,ls ,rs ; int lpos ,rpos ; inline void Build(int &x,int l,int r,bool lft){ x=++ncnt; if (l==r){ if (lft) lpos[l]=x; else rpos[l]=x; return; } int mid=(l+r)>>1; Build(ls[x],l,mid,lft); Build(rs[x],mid+1,r,lft); if (lft) S::add(ls[x],x,0); else S::add(x,ls[x],0); if (lft) S::add(rs[x],x,0); else S::add(x,rs[x],0); } inline void Link(int x,int l,int r,int ql,int qr,int idx,bool lft){ if (ql<=l && r<=qr){ if (lft) S::add(x,idx,0); else S::add(idx,x,0); return; } int mid=(l+r)>>1; if (ql<=mid) Link(ls[x],l,mid,ql,qr,idx,lft); if (qr>mid) Link(rs[x],mid+1,r,ql,qr,idx,lft); } inline void LLink(int a,int b,int c,int d,int x){ if (a>b || c>d) return; Link(lrt,1,clk,a,b,ncnt+1,1); Link(rrt,1,clk,c,d,ncnt+2,0); S::add(ncnt+1,ncnt+2,x); ncnt+=2; } inline void Work(int Rt,int x){ clk=0; dfs(Rt); Build(lrt,1,clk,1); Build(rrt,1,clk,0); for (int j=0;j<ind[x].size();j++) S::add(ind[x][j]+m,lpos[pre[pos[ind[x][j]]]],0); for (int j=0;j<outd[x].size();j++) S::add(rpos[pre[pos[outd[x][j]]]],outd[x][j],0); for (int i=1;i<=clk;i++){ int u=back[i]; LLink(pre[u],pre[u],pre[u],pre[u]+size[u]-1,depth[u]-1); for (int p=Head(u);p;p=G[p].next){ LLink(pre[V],pre[V]+size[V]-1,pre[u],pre[V]-1,depth[u]-1); LLink(pre[V],pre[V]+size[V]-1,pre[V]+size[V],pre[u]+size[u]-1,depth[u]-1); } } } } int tot,a[N<<2]; int sta[N<<2],pnt; inline bool cmp(int x,int y){ return pre[x]<pre[y]; } inline void Solve(int x){ tot=0; for (int j=0;j<ind[x].size();j++) a[++tot]=pos[ind[x][j]]; for (int j=0;j<outd[x].size();j++) a[++tot]=pos[outd[x][j]]; sort(a+1,a+tot+1,cmp); tot=unique(a+1,a+tot+1)-a-1; pnt=0; int rt=0; XS::Clk++; XS::inum=0; for (int i=1;i<=tot;i++){ if (!rt || depth[a[i]]<depth[rt]) rt=a[i]; if (!pnt) { sta[++pnt]=a[i]; continue; } int lca=LCA(sta[pnt],a[i]); if (!rt || depth[lca]<depth[rt]) rt=lca; while (pnt && depth[lca]<depth[sta[pnt]]){ if (depth[lca]>=depth[sta[pnt-1]]){ XS::add(lca,sta[pnt]); if (sta[--pnt]!=lca) sta[++pnt]=lca; break; } pnt--,XS::add(sta[pnt],sta[pnt+1]); } sta[++pnt]=a[i]; } while (--pnt) XS::add(sta[pnt],sta[pnt+1]); XS::Work(rt,x); } ll Dis ; int main(){ int T; int x,y,z; freopen("t.in","r",stdin); freopen("t.out","w",stdout); read(T); while (T--){ read(n); read(m); read(K); for (int i=1;i<=m;i++){ read(iu[i]); read(iv[i]); read(w[i]); read(pos[i]); ind[iv[i]].pb(i); outd[iu[i]].pb(i); } for (int i=1;i<K;i++) read(x),read(y),read(z),add(x,y,++inum); dfs(1,0); for (int i=1;i<=m;i++) S::add(i,i+m,w[i]); ncnt=2*m; for (int i=1;i<=n;i++) if (ind[i].size() && outd[i].size()) Solve(i); S::Dij(ncnt); for (int i=1;i<=n;i++) Dis[i]=1LL<<60; for (int i=1;i<=m;i++) Dis[iv[i]]=min(Dis[iv[i]],S::dis[m+i]); for (int i=2;i<=n;i++) print(Dis[i]),putchar('\n'); cl(head); inum=0; clk=0; ncnt=0; S::clear(); for (int i=1;i<=n;i++) ind[i].clear(),outd[i].clear(); } return 0; }
相关文章推荐
- bzoj 4912: [Sdoi2017]天才黑客 最短路+dfs序优化建图
- BZOJ4912 [Sdoi2017]天才黑客 【虚树 + 最短路】
- BZOJ4912 : [Sdoi2017]天才黑客
- bzoj 4912: [Sdoi2017]天才黑客
- [bzoj3073][Pa2011]Journeys 线段树优化建边的最短路
- BZOJ 3073 [Pa2011]Journeys 最短路 线段树优化建图
- bzoj 3073: [Pa2011]Journeys -- 线段树优化最短路
- BZOJ 3073: [Pa2011]Journeys 线段树优化最短路
- BZOJ 4276 ONTAK2015 Bajtman i Okrągły Robin 费用流+线段树优化构图
- BZOJ 4276: [ONTAK2015]Bajtman i Okrągły Robin [线段树优化建边]
- [线段树优化 DP] BZOJ 3242 [Noi2013]快餐店
- [BZOJ4373][线段树]算术天才⑨与等差数列
- bzoj 3790: 神奇项链 (manacher+线段树优化DP)
- 【BZOJ1576】[Usaco2009 Jan]安全路经Travel【最短路树】【树链剖分】【线段树】
- bzoj 4821: [Sdoi2017]相关分析 线段树
- bzoj 1835: [ZJOI2010]base 基站选址(线段树优化dp)
- bzoj1835(线段树优化dp)
- bzoj 4817: [Sdoi2017]树点涂色 LCT+树链剖分+线段树
- 【bzoj4276】[ONTAK2015]Bajtman i Okrągły Robin 费用流+线段树优化建图
- 线段树 bzoj4373 算术天才⑨与等差数列