zoukankan      html  css  js  c++  java
  • 解题:AHOI 2005 航线规划

    题面

    这种不断删边的首先肯定想到时光倒流啊=。=

    在最后剩下的连通图上跑出一棵搜索树,先将边权都赋为$1$,那么两点间的关键航线就是链上边权和,而每加入一条非树边$u,v$都会使得$u,v$链上的边的边权变为零。写个树剖,先把非树边加进去,然后逆着做一下就行了。

      1 #include<map>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 using namespace std;
      6 const int N=30005,M=100005,Q=40005;
      7 struct a
      8 {
      9     int n1,n2,t;
     10     int mn(){return min(n1,n2);}
     11     int mx(){return max(n1,n2);}
     12 }edg[M],qry[Q];
     13 bool operator < (a x,a y)
     14 {
     15     return x.mn()==y.mn()?x.mx()<y.mx():x.mn()<y.mn(); 
     16 } 
     17 map<a,bool> mp;
     18 int n,m,typ,tot,num,cnt;
     19 int p[N],noww[2*M],goal[2*M];
     20 int vis[N],outp[Q],val[4*N],laz[4*N];
     21 int dfn[N],siz[N],anc[N],dep[N],imp[N],top[N];
     22 void link(int f,int t)
     23 {
     24     noww[++cnt]=p[f];
     25     goal[cnt]=t,p[f]=cnt;
     26 }
     27 void DFS(int nde,int fth,int dth)
     28 {
     29     int tmp=0;
     30     siz[nde]=1,vis[nde]=true;
     31     anc[nde]=fth,dep[nde]=dth;
     32     for(int i=p[nde];i;i=noww[i])
     33         if(goal[i]!=fth&&!vis[goal[i]])
     34         {
     35             mp[(a){nde,goal[i],0}]=true;
     36             DFS(goal[i],nde,dth+1);
     37             siz[nde]+=siz[goal[i]];
     38             if(siz[goal[i]]>tmp)
     39                 tmp=siz[goal[i]],imp[nde]=goal[i];
     40         }
     41 }
     42 void mark(int nde,int tpp)
     43 {
     44     top[nde]=tpp,dfn[nde]=++num;
     45     if(imp[nde])
     46     {
     47         mark(imp[nde],tpp);
     48         for(int i=p[nde];i;i=noww[i])
     49             if(goal[i]!=imp[nde]&&goal[i]!=anc[nde])
     50                 mark(goal[i],goal[i]);
     51     }
     52 }
     53 void create(int nde,int l,int r)
     54 {
     55     if(l==r) 
     56         val[nde]=1,laz[nde]=-1;
     57     else
     58     {
     59         int mid=(l+r)/2,ls=2*nde,rs=2*nde+1;
     60         create(ls,l,mid),create(rs,mid+1,r);
     61         val[nde]=val[ls]+val[rs],laz[nde]=-1; 
     62     }
     63 }
     64 void release(int nde,int l,int r)
     65 {
     66     if(~laz[nde])
     67     {
     68         int mid=(l+r)/2,ls=2*nde,rs=2*nde+1;
     69         laz[ls]=laz[nde],laz[rs]=laz[nde];
     70         val[ls]=(mid-l+1)*laz[nde];
     71         val[rs]=(r-mid)*laz[nde];
     72         laz[nde]=-1;
     73     }
     74 }
     75 void change(int nde,int l,int r,int nl,int nr,int task)
     76 {
     77     if(l>nr||r<nl)
     78         return ;
     79     else if(l>=nl&&r<=nr)
     80         val[nde]=task*(r-l+1),laz[nde]=task;
     81     else
     82     {
     83         int mid=(l+r)/2,ls=2*nde,rs=2*nde+1; release(nde,l,r);
     84         change(ls,l,mid,nl,nr,task),change(rs,mid+1,r,nl,nr,task);
     85         val[nde]=val[ls]+val[rs];
     86     }
     87 }
     88 int query(int nde,int l,int r,int nl,int nr)
     89 {
     90     if(l>nr||r<nl)
     91         return 0;
     92     else if(l>=nl&&r<=nr)
     93         return val[nde];
     94     else
     95     {
     96         int mid=(l+r)/2,ls=2*nde,rs=2*nde+1; release(nde,l,r);
     97         return query(ls,l,mid,nl,nr)+query(rs,mid+1,r,nl,nr);
     98     }
     99 }
    100 int LCA(int x,int y)
    101 {
    102     while(top[x]!=top[y])
    103     {
    104         if(dep[top[x]]<dep[top[y]]) 
    105         swap(x,y); x=anc[top[x]];
    106     }
    107     return dep[x]<dep[y]?x:y;
    108 }
    109 void path_change(int x,int y)
    110 {
    111     int lca=LCA(x,y),mem=query(1,1,n,dfn[lca],dfn[lca]);
    112     while(top[x]!=top[y])
    113     {
    114         if(dep[top[x]]<dep[top[y]]) swap(x,y);
    115         change(1,1,n,dfn[top[x]],dfn[x],0); x=anc[top[x]];
    116     }
    117     if(dep[x]>dep[y]) swap(x,y);
    118     change(1,1,n,dfn[x],dfn[y],0),change(1,1,n,dfn[lca],dfn[lca],mem);
    119 }
    120 int path_query(int x,int y)
    121 {
    122     int ret=0;
    123     while(top[x]!=top[y])
    124     {
    125         if(dep[top[x]]<dep[top[y]]) swap(x,y);
    126         ret+=query(1,1,n,dfn[top[x]],dfn[x]); x=anc[top[x]];
    127     }
    128     if(dep[x]>dep[y]) swap(x,y);
    129     int lca=LCA(x,y),dec=query(1,1,n,dfn[lca],dfn[lca]);
    130     return ret+query(1,1,n,dfn[x],dfn[y])-dec;
    131 }
    132 int main ()
    133 {
    134     scanf("%d%d",&n,&m);
    135     for(int i=1;i<=m;i++)
    136     {
    137         scanf("%d%d",&edg[i].n1,&edg[i].n2);
    138         mp[edg[i]]=true;
    139     }
    140     while(scanf("%d",&typ)&&~typ)
    141     {
    142         qry[++tot].t=typ;
    143         scanf("%d%d",&qry[tot].n1,&qry[tot].n2);
    144         if(!typ) mp[qry[tot]]=false;
    145     }
    146     for(int i=1;i<=m;i++)
    147         if(mp[edg[i]]) 
    148         {
    149             link(edg[i].n1,edg[i].n2);
    150             link(edg[i].n2,edg[i].n1); 
    151         }
    152     mp.clear(); DFS(1,0,1); 
    153     memset(p,0,sizeof p),cnt=0;
    154     for(int i=1;i<=m;i++)
    155         if(mp[edg[i]]) 
    156         {
    157             link(edg[i].n1,edg[i].n2);
    158             link(edg[i].n2,edg[i].n1);  
    159         }
    160     mark(1,1); create(1,1,n); 
    161     for(int i=1;i<=tot;i++)
    162         if(!qry[i].t) mp[qry[i]]=true;
    163     for(int i=1;i<=m;i++)
    164         if(!mp[edg[i]]) path_change(edg[i].n1,edg[i].n2);
    165     for(int i=tot;i;i--)
    166     {
    167         if(qry[i].t) outp[++outp[0]]=path_query(qry[i].n1,qry[i].n2);
    168         else path_change(qry[i].n1,qry[i].n2);
    169     }
    170     while(outp[0]) printf("%d
    ",outp[outp[0]--]);
    171     return 0;
    172 }
    View Code
  • 相关阅读:
    75张图带你了解网络设备、网络地址规划、静态路由、实战演练
    37张图详解MAC地址、以太网、二层转发、VLAN
    用Python计算最长公共子序列和最长公共子串(转)
    python多线程为什么不能利用多核cpu
    python实现leetcode算法题库-maxLengthofRepeatedSubarray-最长公共子序列(718)
    python实现leetcode算法题库-twoSum-两数之和(1)
    python字符串与列表及字典的相互转化
    python sorted函数的使用
    python 2/3重定向输出文件
    elasticsearch查询时设置最大返回数 max_result_window | 限制字段总数超1000
  • 原文地址:https://www.cnblogs.com/ydnhaha/p/9841500.html
Copyright © 2011-2022 走看看