首先跑一边kruskal,以MST的边建树。
若边在MST中则输出mincost
否则新加入的边将构成环,则需要去掉MST中u->v路径上的w最大边
询问也可用线段树,这里只需要维护最值,用RMQ编程复杂度低些(其实是懒
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include"cstdio" #include"queue" #include"cmath" #include"stack" #include"iostream" #include"algorithm" #include"cstring" #include"queue" #include"vector" #define ll long long using namespace std; const int MAXN = 200050; const int MAXE = 400050; const int INF = 0x3f3f3f3f; int f[MAXN],first[MAXN],mark[MAXE],top[MAXN],dep[MAXN],faa[MAXN],siz[MAXN],son[MAXN],id[MAXN],val[MAXN]; ll dp[MAXN][20]; int n,m,tot,cnt; ll cost,ans[MAXN]; struct nod{ int u,v,w,o; }E[MAXN]; bool cmp(nod a,nod b){ return a.w<b.w; } struct node{ int e,next; node(){} node(int a,int b):e(a),next(b){} }edge[MAXN*2]; int fa(int x){ return x==f[x]?x:f[x]=fa(f[x]); } void init(){ tot=0; cost=0; cnt=-1; for(int i=1;i<=m;i++) f[i]=i; memset(first,-1,sizeof(first)); memset(mark,0,sizeof(mark)); memset(son,-1,sizeof(son)); } void mer(int a,int b){ a=fa(a); b=fa(b); f[a]=b; } void addedge(int u,int v){ edge[tot]=node(v,first[u]); first[u]=tot++; edge[tot]=node(u,first[v]); first[v]=tot++; } void kruskal(){ for(int i=0;i<m;i++){ if(fa(E[i].u)!=fa(E[i].v)){ mer(E[i].u,E[i].v); cost+=(ll)E[i].w; addedge(E[i].u,E[i].v); mark[i]=1; } } } void dfs1(int u,int pre,int depth){ siz[u]=1; dep[u]=depth; faa[u]=pre; for(int i=first[u];i!=-1;i=edge[i].next){ int v=edge[i].e; if(v==pre) continue; dfs1(v,u,depth+1); siz[u]+=siz[v]; if(son[u]==-1||siz[son[u]]<siz[v]) son[u]=v; } } void dfs2(int u,int tp){ top[u]=tp; id[u]=cnt++; if(son[u]==-1) return; dfs2(son[u],tp); for(int i=first[u];i!=-1;i=edge[i].next){ int v=edge[i].e; if(v==faa[u]||v==son[u]) continue; dfs2(v,v); } } int makermq(int N){ for(int i=0;i<N;i++) dp[i][0]=val[i]; for(int j=1;(1<<j)<=N;j++) for(int i=0;i+(1<<j)-1<N;i++) dp[i][j]=max(dp[i][j-1],dp[i+(1<<(j-1))][j-1]); } ll query(int l,int r){ int k=(int)(log((r-l+1)*1.0)/log(2.0)); return max(dp[l][k],dp[r-(1<<k)+1][k]); } ll findmax(int u,int v){ int tu=top[u],tv=top[v]; ll ans=-INF; while(tu!=tv){ if(dep[tu]<dep[tv]){ swap(tu,tv); swap(u,v); } ans=max(ans,query(id[tu],id[u])); u=faa[u]; tu=top[u]; } if(u==v) return ans; if(dep[u]>dep[v]) swap(u,v); return max(ans,query(id[son[u]],id[v])); } int main(){ //freopen("in.txt","r",stdin); scanf("%d%d",&n,&m); init(); for(int i=0;i<m;i++) { scanf("%d%d%d",&E[i].u,&E[i].v,&E[i].w); E[i].o=i; } sort(E,E+m,cmp); kruskal(); dfs1(1,0,1); dfs2(1,1); for(int i=0;i<m;i++){ if(!mark[i]) continue; if(dep[E[i].u]<dep[E[i].v]) swap(E[i].u,E[i].v); val[id[E[i].u]]=E[i].w; } makermq(n); for(int i=0;i<m;i++){ if(mark[i]) ans[E[i].o]=cost; else{ ll t=findmax(E[i].u,E[i].v); ans[E[i].o]=cost+(ll)(E[i].w-t); } } for(int i=0;i<m;i++) printf("%I64d ",ans[i]); return 0; }