A. Minimum spanning tree for each edge
先建出最小生成树,对于树边答案就是最小生成树,对于非树边就从两个端点的路径上删掉权值最大的即可。
证明:在这个环中,首先强制选了这条边,然后按照从小到大的顺序选边,则一定不会选到删掉的那条边。
Code
#include<bits/stdc++.h>
#define int long long
#define il inline
#define pb push_back
#define pii pair<int,int>
#define mp make_pair
#define fir first
#define sec second
using namespace std;
namespace asbt{
namespace cplx{bool begin;}
const int maxn=2e5+5;
int n,m,fa[maxn],sz[maxn],dep[maxn];
int anc[maxn][22],mxv[maxn][22],ans[maxn];
bool vis[maxn];
struct edge{int u,v,w,id;il bool operator<(const edge &x)const{return w<x.w;}
}a[maxn];
vector<pii> e[maxn];
il int find(int x){return x!=fa[x]?fa[x]=find(fa[x]):x;
}
il void merge(int u,int v){u=find(u),v=find(v);if(u==v){return ;}if(sz[u]>sz[v]){sz[u]+=sz[v],fa[v]=u;}else{sz[v]+=sz[u],fa[u]=v;}
}
il void dfs(int u){
// cout<<u<<" "<<anc[u][0]<<"\n";for(int i=1;i<=20;i++){anc[u][i]=anc[anc[u][i-1]][i-1];mxv[u][i]=max(mxv[u][i-1],mxv[anc[u][i-1]][i-1]);}for(pii i:e[u]){int v=i.fir,w=i.sec;if(v==anc[u][0]){continue;}anc[v][0]=u,mxv[v][0]=w;dep[v]=dep[u]+1;dfs(v);}
}
il int query(int u,int v){
// cout<<u<<" "<<v<<"\n";if(dep[u]<dep[v]){swap(u,v);}int ddep=dep[u]-dep[v],tmp=0,res=0;while(ddep){if(ddep&1){res=max(res,mxv[u][tmp]);u=anc[u][tmp];}ddep>>=1,tmp++;}
// cout<<u<<" "<<v<<"\n";if(u==v){
// puts("666");return res;}for(int i=20;~i;i--){if(anc[u][i]!=anc[v][i]){res=max({res,mxv[u][i],mxv[v][i]});u=anc[u][i],v=anc[v][i];}}return max({res,mxv[u][0],mxv[v][0]});
}
namespace cplx{bool end;il double usdmem(){return (&begin-&end)/1048576.0;}
}
signed main(){ios::sync_with_stdio(0),cin.tie(0);cin>>n>>m;for(int i=1;i<=m;i++){cin>>a[i].u>>a[i].v>>a[i].w;a[i].id=i;}sort(a+1,a+m+1);for(int i=1;i<=n;i++){fa[i]=i,sz[i]=1;}int res=0;for(int i=1,u,v,w;i<=m;i++){u=a[i].u,v=a[i].v,w=a[i].w;if(find(u)!=find(v)){merge(u,v);vis[i]=1,res+=w;e[u].pb(mp(v,w));e[v].pb(mp(u,w));}}
// for(int i=1;i<=m;i++){
// if(vis[i]){
// cout<<a[i].id<<" ";
// }
// }
// puts("");dfs(1);
// for(int u=1;u<=n;u++){
// for(int i=0;i<=3;i++){
// cout<<mxv[u][i]<<" ";
// }
// puts("");
// }for(int i=1;i<=m;i++){if(vis[i]){ans[a[i].id]=res;}else{
// cout<<a[i].id<<" "<<query(a[i].u,a[i].v)<<"\n";ans[a[i].id]=res-query(a[i].u,a[i].v)+a[i].w;}}for(int i=1;i<=m;i++){cout<<ans[i]<<"\n";}return 0;
}
}
signed main(){return asbt::main();}