解题: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\n",outp[outp[0]--]);
171     return 0;
172 }
View Code

猜你喜欢

转载自www.cnblogs.com/ydnhaha/p/9841500.html
今日推荐