这种不断删边的首先肯定想到时光倒流啊=。=
在最后剩下的连通图上跑出一棵搜索树,先将边权都赋为$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 }