链剖-进阶ing-填坑-NOIP2013-货车运输
Posted Jason-Cow
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了链剖-进阶ing-填坑-NOIP2013-货车运输相关的知识,希望对你有一定的参考价值。
This article is made by Jason-Cow.
Welcome to reprint.
But please post the writer\'s address.
http://www.cnblogs.com/JasonCow/
感谢您的关注,赠送数据生成器一个
#include <ctime> #include <cstdio> #include <iostream> #include <algorithm> using namespace std; #define sizen 10 #define sizem 10 #define sizew 32767 #define sizeq 20 int main(){ freopen("car.in","w",stdout); srand(time(NULL)); int n=rand()%sizen+5,m=rand()%sizem+3; cout<<n<<" "<<m<<endl; while(m--){ int u=rand()%n+1,v=rand()%n+1; if(u==v)u=(u-2+n)%n+1; cout<<u<<" "<<v<<" "<<rand()%sizew+10<<endl; } int q=rand()%sizeq+10; cout<<q<<endl; while(q--){ int u=rand()%n+1,v=rand()%n+1; if(u==v)u=(u-1+n)%n; cout<<u<<" "<<v<<endl; } return 0; }
似乎官方给的是倍增lca
不管了,最近练习链剖,以后有时间在补倍增的写法
就是边权下放成点权,然后树链剖分套一颗线段树就可以了
开始sb似的建成一颗大树,其实直接利用Kruskal的并查集查询是否在同一子树就好了[森林x1森林x2森林x3重要的事说三遍]
ac code 莫名压行,不压不爽
1 //边权的下放,可能是这题唯一的细节吧 2 #include <cstdio> 3 #include <algorithm> 4 #define E(u,v,w) e[++cnt]=(edge){v,w,head[u]},head[u]=cnt 5 using namespace std; 6 int GI(){ 7 int x=0,c=getchar(),f=0; 8 while(c<\'0\'||c>\'9\'){if(c==\'-\')f=1;c=getchar();} 9 while(c>=\'0\'&&c<=\'9\')x=x*10+c-\'0\',c=getchar(); 10 return f?-x:x; 11 } 12 const int maxn=20000,maxm=80000; 13 struct edge{int v,w,next;}e[maxm*2]; 14 struct data{int u,v,w;}a[maxm]; 15 int n,m,q,head[maxn],cnt,f[maxn],vis[maxn]; 16 int find(int x){return f[x]==x?x:f[x]=find(f[x]);} 17 bool operator<(data x,data y){return x.w>y.w;} 18 void add(int u,int v,int w){E(u,v,w),E(v,u,w);} 19 void kruskal(){ 20 sort(a+1,a+m+1); 21 for(int i=1;i<=n;i++)f[i]=i; 22 for(int i=1,tot=0;i<=m;i++){ 23 int u=a[i].u,v=a[i].v; 24 int x=find(u),y=find(v); 25 if(x!=y)f[x]=y,add(a[i].u,a[i].v,a[i].w),++tot; 26 if(tot==n-1)return; 27 } 28 } 29 int dfn[maxn],dep[maxn],fa[maxn],top[maxn],son[maxn],rak[maxn],siz[maxn],idx,W[maxn]; 30 void dfs1(int u,int _fa){ 31 siz[u]=1,fa[u]=_fa,dep[u]=dep[_fa]+1; 32 for(int i=head[u];i;i=e[i].next) 33 if(e[i].v!=_fa){ 34 dfs1(e[i].v,u),siz[u]+=siz[e[i].v],W[e[i].v]=e[i].w;//细节1 35 if(!son[u]||siz[e[i].v]>siz[son[u]])son[u]=e[i].v; 36 } 37 } 38 void dfs2(int u,int _top){ 39 dfn[u]=++idx,rak[dfn[u]]=u,top[u]=_top; 40 if(son[u])dfs2(son[u],_top); 41 for(int i=head[u];i;i=e[i].next) 42 if(e[i].v!=fa[u]&&e[i].v!=son[u])dfs2(e[i].v,e[i].v); 43 } 44 #define ls (x<<1) 45 #define rs (x<<1|1) 46 #define mid ((l+r)>>1) 47 int Min[maxn<<2]; 48 void up(int x){Min[x]=min(Min[ls],Min[rs]);} 49 void build(int x,int l,int r){ 50 if(l==r)Min[x]=W[rak[l]]; 51 else build(ls,l,mid),build(rs,mid+1,r),up(x); 52 } 53 int MIN(int x,int l,int r,int L,int R){ 54 if(L>R)return 1<<30; 55 if(L<=l&&r<=R)return Min[x]; 56 if(R<=mid)return MIN(ls,l,mid,L,R); 57 if(L>mid)return MIN(rs,mid+1,r,L,R); 58 return min(MIN(ls,l,mid,L,R),MIN(rs,mid+1,r,L,R)); 59 } 60 int jump(int x,int y){ 61 if(find(x)!=find(y))return -1; 62 int ans=1<<30; 63 while(top[x]!=top[y]){ 64 if(dep[top[x]]<dep[top[y]])swap(x,y); 65 ans=min(ans,MIN(1,1,n,dfn[top[x]],dfn[x])); 66 x=fa[top[x]]; 67 } 68 if(dep[x]>dep[y])swap(x,y); 69 ans=min(ans,MIN(1,1,n,dfn[x]+1,dfn[y]));//细节2 70 return ans; 71 } 72 int main(){ 73 freopen("car.in","r",stdin); 74 freopen("car.out","w",stdout); 75 int i;n=GI(),m=GI(); 76 for(i=1;i<=m;i++)a[i].u=GI(),a[i].v=GI(),a[i].w=GI(); 77 for(kruskal(),i=1;i<=n;i++)if(!dfn[i])dfs1(i,0),dfs2(i,i); 78 for(build(1,1,n),q=GI(),i=1;i<=q;i++)printf("%d\\n",jump(GI(),GI())); 79 return 0; 80 }
以上是关于链剖-进阶ing-填坑-NOIP2013-货车运输的主要内容,如果未能解决你的问题,请参考以下文章