zoukankan      html  css  js  c++  java
  • 链剖进阶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 }
    ~~Jason_liu O(∩_∩)O
  • 相关阅读:
    Flexbox
    jquery.cropper 裁剪图片上传
    让Sublime Text3支持Less
    css实现图片垂直居中
    手淘适配-flexible
    CSSREM
    vue.js+boostrap最佳实践
    最好用的技术是最基础的
    响应式网页布局
    php基础入门
  • 原文地址:https://www.cnblogs.com/JasonCow/p/6703471.html
Copyright © 2011-2022 走看看