显然先求出最小生成树
如果删的是非树边就不用管,还是能取最小生成树
如果删的是树边就有非树边可以替代它
反向考虑,每条非树边可以替代最小生成树上一条路径的边
所以树剖加线段树,对每条非树边在树上更新对应的那一段的答案就行了
代码异常丑陋~~~
#include#define il inline#define vd voidtypedef long long ll;il int gi(){ int x=0,f=1; char ch=getchar(); while(!isdigit(ch)){ if(ch=='-')f=-1; ch=getchar(); } while(isdigit(ch))x=x*10+ch-'0',ch=getchar(); return x*f;}struct edge{int x,y,i,w;}s[100010];il bool cmp1(const edge&a,const edge&b){return a.w >1)il vd update(int x,int l,int r,const int&L,const int&R,const int&d){ if(L<=l&&r<=R){lz[x]=std::min(lz[x],d);return;} if(L<=mid)update(x<<1,l,mid,L,R,d); if(mid <<1|1,mid+1,r,L,R,d);}il vd down(int x,int l,int r){ if(l==r){ans[l]=lz[x];return;} lz[x<<1]=std::min(lz[x<<1],lz[x]); lz[x<<1|1]=std::min(lz[x<<1|1],lz[x]); down(x<<1,l,mid),down(x<<1|1,mid+1,r);}int main(){#ifndef ONLINE_JUDGE freopen("2238.in","r",stdin); freopen("2238.out","w",stdout);#endif int n=gi(),m=gi(); for(int i=1;i<=m;++i)s[i].x=gi(),s[i].y=gi(),s[i].w=gi(),s[i].i=i; std::sort(s+1,s+m+1,cmp1); int q=gi(); for(int i=1;i<=n;++i)Fa[i]=i; int t=1;ll ANS=0; for(int i=1;i m){ while(q--)puts("Not connected"); return 0; } Union(s[t].x,s[t].y); link(s[t].x,s[t].y,s[t].i); ANS+=s[t].w; } std::sort(s+1,s+m+1,cmp2); dfs(1),dfs2(1,1); for(int i=1;i<=n*4;++i)lz[i]=1e9; for(int i=1;i<=m;++i) if(!NUM[i]){ int x=s[i].x,y=s[i].y; while(top[x]!=top[y]){ if(dep[top[x]]>dep[top[y]])update(1,1,n,dfn[top[x]],dfn[x],s[i].w),x=fa[top[x]]; else update(1,1,n,dfn[top[y]],dfn[y],s[i].w),y=fa[top[y]]; } if(dep[x]>dep[y])std::swap(x,y); update(1,1,n,dfn[x]+1,dfn[y],s[i].w); } down(1,1,n); while(q--){ int x=gi(); if(NUM[x]){ if(ans[dfn[NUM[x]]]==1e9)puts("Not connected"); else printf("%lld\n",ANS-s[x].w+ans[dfn[NUM[x]]]); }else printf("%lld\n",ANS); } return 0;}