• 树剖+线段树||树链剖分||BZOJ2238||Mst


    题面:https://www.lydsy.com/JudgeOnline/problem.php?id=2238

    思路:先求个最小生成树,然后就对最小生成树上的边做树剖,依次对非树边进行处理,维护非树边两端连成的路径的最小值(用非树边的权值维护),然后对于每个询问,求出覆盖在那条线段上的最小值,用real_sum(最小生成树的边权和)去加加减减就行了。

      1 #include<cstdio>
      2 #include<iostream>
      3 #include<cstring>
      4 #include<algorithm>
      5 #include<cstdlib>
      6 #define min(a,b) ((a)<(b)?(a):(b))
      7 using namespace std;
      8 const int maxn=50005,maxm=100005,maxw=10005,inf=1<<30;
      9 int N,M,x,y,w,Q,edge_head[maxn],num_edge=0,edge_head2[maxn],num_edge2=0,fa[maxn],real_sum=0;
     10 int size[maxn],son[maxn],seg[maxn],rev[maxn],f[maxn],dep[maxn],top[maxn],X,Y,_ans,T;
     11 bool via[maxm],ans=1;
     12 inline int rd(){
     13     int x=0,f=1;char c=getchar();
     14     while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
     15     while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
     16     return f*x;
     17 }
     18 struct Edge{
     19     int to,dis,nx,from;
     20 }edge[maxm<<1];
     21 struct Edge2{
     22     int to,dis,nx,from,id;
     23 }edge2[maxm];
     24 inline void Add_edge(int from,int to,int dis){
     25     edge[++num_edge].nx=edge_head[from];
     26     edge[num_edge].from=from;
     27     edge[num_edge].to=to;
     28     edge[num_edge].dis=dis;
     29     edge_head[from]=num_edge;
     30     return;
     31 }
     32 inline void Add_edge2(int from,int to,int dis){
     33     edge2[++num_edge2].nx=edge_head2[from];
     34     edge2[num_edge2].from=from;
     35     edge2[num_edge2].to=to;
     36     edge2[num_edge2].dis=dis;
     37     edge2[num_edge2].id=num_edge2;
     38     edge_head2[from]=num_edge2;
     39     return;
     40 }
     41 inline bool cmp(const Edge2&a,const Edge2&b){
     42     if(a.dis<b.dis)return 1;
     43     return 0;
     44 }
     45 inline int getf(int x){
     46     if(fa[x]==x)return x;
     47     fa[x]=getf(fa[x]);
     48     return fa[x];
     49 }
     50 void Kruskal(){
     51     sort(edge2+1,edge2+num_edge2+1,cmp);
     52     for(int i=1;i<=N;i++)fa[i]=i;
     53     int num=0;
     54     for(int i=1;i<=num_edge2;i++){
     55         int x=edge2[i].from,y=edge2[i].to;
     56         int fx=getf(x),fy=getf(y);
     57         if(fx!=fy){
     58             num++;
     59             fa[fx]=fy;
     60             via[edge2[i].id]=1;
     61             real_sum+=edge2[i].dis;
     62             if(num==N-1)break;
     63         }
     64     }
     65     if(num!=N-1)ans=0;
     66     return;
     67 }
     68 inline void Dfs1(int x,int _f){
     69     f[x]=_f;
     70     size[x]=1;
     71     dep[x]=dep[_f]+1;
     72     for(int i=edge_head[x];i;i=edge[i].nx){
     73         int y=edge[i].to;
     74         if(y!=_f&&((((i&1)==1)&&via[(i>>1)+1])||(((i&1)==0)&&via[i>>1]))){
     75             Dfs1(y,x);
     76             size[x]+=size[y];
     77             if(size[y]>size[son[x]])son[x]=y;
     78         }
     79     }
     80     return;
     81 }
     82 inline void Dfs2(int x){
     83     if(son[x]){
     84         int y=son[x];
     85         top[y]=top[x];
     86         seg[y]=++seg[0];
     87         rev[seg[0]]=y;
     88         Dfs2(y);
     89     }
     90     for(int i=edge_head[x];i;i=edge[i].nx){
     91         int y=edge[i].to;
     92         if(top[y]==0&&((((i&1)==1)&&via[(i>>1)+1])||(((i&1)==0)&&via[i>>1]))){
     93             top[y]=y;
     94             seg[y]=++seg[0];
     95             rev[seg[0]]=y;
     96             Dfs2(y);
     97         }
     98     }
     99     return;
    100 }
    101 struct Tree{
    102     int l,r,mina,lazy;
    103 }t[maxn<<3];
    104 inline void Build(int x,int l,int r){
    105     t[x].l=l;t[x].r=r;t[x].mina=inf;t[x].lazy=inf;
    106     if(l==r)return;
    107     int ls=x<<1,rs=x<<1|1,mid=(l+r)>>1;
    108     Build(ls,l,mid);Build(rs,mid+1,r);
    109     return;
    110 }
    111 inline void Pushdown(int x){
    112     int ls=x<<1,rs=x<<1|1,lazy=t[x].lazy;
    113     if(lazy!=inf){
    114         t[ls].mina=min(t[ls].mina,lazy);t[rs].mina=min(t[rs].mina,lazy);
    115         t[ls].lazy=min(t[ls].lazy,lazy);t[rs].lazy=min(t[rs].lazy,lazy);
    116         t[x].lazy=inf;
    117     }
    118     return;
    119 }
    120 inline void Update(int x,int ql,int qr,int e){
    121     int l=t[x].l,r=t[x].r;
    122     if(ql<=l&&r<=qr){
    123         t[x].mina=min(t[x].mina,e);
    124         t[x].lazy=min(t[x].lazy,e);
    125         return;
    126     }
    127     int ls=x<<1,rs=x<<1|1,mid=(l+r)>>1;
    128     Pushdown(x);
    129     if(ql<=mid)Update(ls,ql,qr,e);
    130     if(qr>mid)Update(rs,ql,qr,e);
    131     return;
    132 }
    133 inline void Query(int x,int q){
    134     int l=t[x].l,r=t[x].r;
    135     if(q==l&&l==r){
    136         _ans=min(_ans,t[x].mina);
    137         return;
    138     }
    139     int mid=(l+r)>>1,ls=x<<1,rs=x<<1|1;
    140     Pushdown(x);
    141     if(q<=mid)Query(ls,q);
    142     else Query(rs,q);
    143     return;
    144 }
    145 inline void Work(int x,int y,int dis){
    146     int fx=top[x],fy=top[y];
    147     while(fx!=fy){
    148         if(dep[fx]<dep[fy])swap(x,y),swap(fx,fy);
    149         Update(1,seg[fx],seg[x],dis);
    150         x=f[fx];fx=top[x];
    151     }
    152     if(dep[x]>dep[y])swap(x,y);
    153     if(x==y)return;
    154     Update(1,seg[x]+1,seg[y],dis);
    155     return;
    156 }
    157 int main(){
    158     N=rd();M=rd();
    159     for(int i=1;i<=M;i++){
    160         x=rd();y=rd();w=rd();
    161         Add_edge2(x,y,w);
    162         Add_edge(x,y,w);
    163         Add_edge(y,x,w);
    164     }
    165     Kruskal();
    166     scanf("%d",&Q);
    167     Dfs1(1,0);
    168     seg[0]=seg[1]=rev[1]=top[1]=1;
    169     Dfs2(1);
    170     Build(1,1,seg[0]);
    171     for(int i=1;i<=M;i++)if(via[i]==0)Work(edge[i<<1].from,edge[i<<1].to,edge[i<<1].dis);
    172     while(Q--){
    173         scanf("%d",&T);
    174         if(ans==0){
    175             puts("Not connected");
    176             continue;
    177         }
    178         if(via[T]==0)printf("%d
    ",real_sum);
    179         else{
    180             X=edge[T<<1].from,Y=edge[T<<1].to;_ans=inf;
    181             if(dep[X]>dep[Y])Query(1,seg[X]);else Query(1,seg[Y]);
    182             if(_ans==inf){
    183                 puts("Not connected");
    184                 continue;
    185             }
    186             _ans=real_sum-edge[T<<1].dis+_ans;
    187             printf("%d
    ",_ans);
    188         }
    189     }
    190     return 0;
    191 }

    后记:“&”的优先级小于“==”的优先级;线段树查询时要注意ql不能大于qr;边权下移后处理点权时要小心;什么情况要pushdown、pushup要考虑清楚;我的线段树真菜

  • 相关阅读:
    127.0.0.1(转) Anny
    轮岗开发后再看测试(转) Anny
    如何做好功能测试的方法(转) Anny
    Search Framework: Search Result checklist(转) Anny
    What is a Private IP Address(转) Anny
    Private IP Addresses(转) Anny
    公共模式资源库链接 Anny
    What is Dynamic DNS? Anny
    随机数产生
    tomcat源码阅读_代码篇4
  • 原文地址:https://www.cnblogs.com/AlenaNuna/p/10356782.html
Copyright © 2020-2023  润新知