zoukankan      html  css  js  c++  java
  • luogu题解P1967货车运输--树链剖分

    题目链接

    https://www.luogu.org/problemnew/show/P1967

    分析

    NOIp的一道裸题,直接在最大生成树上剖分取最小值一下就完事了,非常好写,常数也比较小,然而题解里有许多我没见过的船新操作,先挖个坑等有时间再看

    注意

    • 树链剖分又在第一遍挂了,忘了写top[now]=t;

    • 注意题目说明并没有保证是联通的!!!然后成功被Hack了.这真的要警惕,指不定哪天毒瘤出题人就在这里把你正解卡成60(flag++)

    代码

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <algorithm>
    #include <cctype>
    #include <vector>
    #include <queue>
    #define ll long ong 
    #define ri register int 
    #define ull unsigned long long 
    using std::vector;
    using std::swap;
    using std::min;
    using std::max;
    using std::sort;
    template <class T>inline void read(T &x){
      x=0;int ne=0;char c;
      while(!isdigit(c=getchar()))ne=c=='-';
      x=c-48;
      while(isdigit(c=getchar()))x=(x<<3)+(x<<1)+c-48;
      x=ne?-x:x;return ;
    }
    const int maxn=10005;
    const int maxm=50005;
    const int inf=0x7fffffff;
    int n,m;
    struct Edge{
      int x,y,c;
      Edge(int _x,int _y,int _c){x=_x,y=_y,c=_c;}
      Edge(){x=y=c=0;}
      bool operator <(const Edge &b)const {
      	return c>b.c;
      } 
    }edge[maxm];
    struct Dat{
      int ver,dis;
      Dat(int x,int y){ver=x,dis=y;}
      Dat(){;}
    };
    vector<Dat>g[maxn]; 
    int pa[maxn];
    int get(int x){
      if(pa[x]!=x)pa[x]=get(pa[x]);//return pa[x]==x?pa[x]:pa[x]=get(pa[x]);
      return pa[x];
    }
    inline void kruskal(){
      int cnt=0,x,y,xx,yy,c;
      sort(edge+1,edge+1+m);
      for(ri i=1;i<=n;i++)pa[i]=i;
      for(ri i=1;i<=m;i++){
      	//printf("%d
    ",edge[i].c);
      	int x=edge[i].x,y=edge[i].y;
      	xx=get(x),yy=get(y);
      	if(xx==yy)continue;
      	c=edge[i].c;
      	//printf("%d %d %d
    ",x,y,c);
      	g[x].push_back(Dat(y,c));
      	g[y].push_back(Dat(x,c));
      	pa[xx]=yy;
      	cnt++;
      	if(cnt==n-1)break;
      }
      return ;
    }
    int dep[maxn],son[maxn],top[maxn],size[maxn],dfn[maxn],fa[maxn],rnk[maxn],tot=0;
    int w[maxn];
    void dfs_1(int now){
      int v;size[now]=1;
      for(ri i=0;i<g[now].size();i++){
      	v=g[now][i].ver;
      	if(v==fa[now])continue;
      	fa[v]=now,dep[v]=dep[now]+1;
      	w[v]=g[now][i].dis;
      	dfs_1(v);
      	size[now]+=size[v];
      	if(!son[now]||size[v]>size[son[now]])son[now]=v;
      }
      return ;
    }
    void dfs_2(int now,int t){
      int v;dfn[now]=++tot,rnk[tot]=now,top[now]=t;
      if(!son[now])return ;
      dfs_2(son[now],t);
      for(ri i=0;i<g[now].size();i++){
      	v=g[now][i].ver;
      	if(v==fa[now]|v==son[now])continue;
      	dfs_2(v,v);
      }
      return ;
    }
    int mi[maxn<<2];
    void build(int now,int l,int r){
      if(l==r){
      	mi[now]=w[rnk[l]];
      	return ;
      }
      int mid=(l+r)>>1;
      build(now<<1,l,mid);
      build(now<<1|1,mid+1,r);
      mi[now]=min(mi[now<<1],mi[now<<1|1]);
      return ;
    }
    int L,R;
    int query(int now,int l,int r){
      if(L<=l&&r<=R){
      	return mi[now];
      }
      int ans=inf,mid=(l+r)>>1;
      if(L<=mid)ans=min(ans,query(now<<1,l,mid));
      if(mid<R)ans=min(ans,query(now<<1|1,mid+1,r));
      return ans;
    }
    inline int query_path(int x,int y){
      int ans=inf;
      while(top[x]!=top[y]){
      	if(dep[top[x]]<dep[top[y]])swap(x,y);
      	L=dfn[top[x]],R=dfn[x];
      	ans=min(ans,query(1,1,n));
      	x=fa[top[x]];
      }
      if(dfn[x]>dfn[y])swap(x,y);
      L=dfn[x]+1,R=dfn[y];
      if(L>R)return ans;
      ans=min(ans,query(1,1,n));
      return ans;
    }
    int main(){
      int q,x,y,z;
      read(n),read(m);
      for(ri i=1;i<=m;i++){
      	read(x),read(y),read(z);
      	edge[i]=Edge(x,y,z);
      }
      kruskal();
      for(ri i=1;i<=n;i++){//不一定联通
      	if(!dfn[i]){
            dep[i]=1,fa[i]=0;
            dfs_1(i);
            dfs_2(i,i);
          }
      }
      build(1,1,n);
      read(q);
      while(q--){
      	read(x),read(y);
      	int tmp=query_path(x,y);
      	if(!tmp)puts("-1");
      	else printf("%d
    ",tmp);
      }
      return 0;
    }
    
  • 相关阅读:
    7/31 CSU-ACM2018暑期训练7-贪心
    树状数组
    洛谷 P2947 [USACO09MAR]向右看齐Look Up【单调栈】
    如何求先序排列和后序排列——hihocoder1049+洛谷1030+HDU1710+POJ2255+UVA548【二叉树递归搜索】
    HDU 1611 敌兵布阵【线段树模板】
    Poj 2112 Optimal Milking (多重匹配+传递闭包+二分)
    Hdu 5361 In Touch (dijkatrs+优先队列)
    Codeforces Round #Pi (Div. 2)
    Hdu 5358 First One (尺取法+枚举)
    Poj 3189 Steady Cow Assignment (多重匹配)
  • 原文地址:https://www.cnblogs.com/Rye-Catcher/p/9428155.html
Copyright © 2011-2022 走看看