Python-爬蟲基礎-原理
阿新 • • 發佈:2022-05-16
需要動態維護一個點集的極小聯通子圖邊權和。可以發現,將點集 \(\{a_i\}\) 中的點按照 dfs 序從小到大排序之後,\(dist(a_1,a_2)+dist(a_2,a_3)+\ldots+dist(a_{k-1},a_k)+dist(a_k,a_1)\) 恰好等於我們要維護的那個邊權和的兩倍。所以就開一個 set
,在加入和刪除的時候加上或刪去 pre
和 nxt
的貢獻即可。
點選檢視程式碼
const int N=1e5+13; struct Edge{int v,w,nxt;}e[N<<1]; int n,m,h[N],tot; ll dis[N]; inline void add_edge(int u,int v,int w){e[++tot]=(Edge){v,w,h[u]};h[u]=tot;} int fa[N],dep[N],siz[N],son[N],top[N],id[N],dfs_clock; void dfs1(int u,int f,int deep){ dep[u]=deep,fa[u]=f,siz[u]=1; int maxson=0; for(int i=h[u];i;i=e[i].nxt){ int v=e[i].v;if(v==f) continue; dis[v]=dis[u]+e[i].w; dfs1(v,u,deep+1); siz[u]+=siz[v]; if(siz[v]>maxson) maxson=siz[v],son[u]=v; } } void dfs2(int u,int topf){ top[u]=topf,id[u]=++dfs_clock; if(!son[u]) return; dfs2(son[u],topf); for(int i=h[u];i;i=e[i].nxt){ int v=e[i].v; if(v!=fa[u]&&v!=son[u]) dfs2(v,v); } } inline int lca(int u,int v){ while(top[u]!=top[v]){ if(dep[top[u]]<dep[top[v]]) swap(u,v); u=fa[top[u]]; } return id[u]<id[v]?u:v; } inline ll dist(int u,int v){return dis[u]+dis[v]-2*dis[lca(u,v)];} struct Node{ int x; bool operator <(const Node &a)const{return id[x]<id[a.x];} }; std::set<Node> t; std::set<Node>::iterator it; int main(){ //file(); read(n),read(m); for(int i=1;i<n;++i){ int u,v,w;read(u),read(v),read(w); add_edge(u,v,w),add_edge(v,u,w); } dfs1(1,0,0),dfs2(1,1); ll sum=0; while(m--){ int x;read(x); if(t.find((Node){x})!=t.end()){//remove it=t.find((Node){x}); int pre=0,nxt=0; if(it!=t.begin()) pre=(--it)->x,it=t.find((Node){x}); if((++it)!=t.end()) nxt=it->x; if(pre) sum-=dist(pre,x);if(nxt) sum-=dist(nxt,x);if(pre&&nxt) sum+=dist(pre,nxt); t.erase((Node){x}); } else{//insert t.insert((Node){x}); it=t.find((Node){x}); int pre=0,nxt=0; if(it!=t.begin()) pre=(--it)->x,it=t.find((Node){x}); if((++it)!=t.end()) nxt=it->x; if(pre) sum+=dist(pre,x);if(nxt) sum+=dist(nxt,x);if(pre&&nxt) sum-=dist(pre,nxt); } it=t.end();--it; if(it!=t.begin()){ int u=it->x;it=t.begin();int v=it->x; println(sum+dist(u,v)); } else println(sum); } return 0; }