2 条题解
-
0

// 最小生成树 kruskal算法 O(M*logM) #include<bits/stdc++.h> #define ll long long using namespace std; const int N=100005,M=300005,INF=0x3f3f3f3f; int idx,h[N],to[M],ne[M],ww[M]; void add(int u,int v,int w){ //连边 to[++idx]=v,ww[idx]=w,ne[idx]=h[u],h[u]=idx; to[++idx]=u,ww[idx]=w,ne[idx]=h[v],h[v]=idx; } int n,m; ll sum; struct E{int u,v,w;}e[M]; //边集 bool used[M]; int fa[N]; //并查集的fa int find(int u){ //并查集的找根 return fa[u]==u?u:fa[u]=find(fa[u]); } void kruskal(){ int tot=0; for(int i=1; i<=n; i++) fa[i]=i; sort(e+1,e+m+1,[&](E u,E v){return u.w<v.w;}); for(int i=1; i<=m; i++){ int u=find(e[i].u),v=find(e[i].v); if(u!=v){ fa[u]=v; sum+=e[i].w; //累加边权和 used[i]=true; //记录树边 add(e[i].u,e[i].v,e[i].w); //建最小生成树 if(++tot==n-1) break; } } } struct Tree{ int fa[N][18],dep[N]; int d1[N][18]; //d1[u][i]表示从u点开始向上跳2^i条边,这条路径上的最大边权 int d2[N][18]; //d2[u][i]表示从u点开始向上跳2^i条边,这条路径上的次大边权,不存在为-INF void dfs(int u,int f){ //预处理fa,d1,d2数组 dep[u]=dep[f]+1; fa[u][0]=f; d2[u][0]=-INF; for(int i=1; i<=17; i++){ fa[u][i]=fa[fa[u][i-1]][i-1]; int d[4]={d1[u][i-1],d1[fa[u][i-1]][i-1],d2[u][i-1],d2[fa[u][i-1]][i-1]}; sort(d,d+4); d1[u][i]=d[3]; //最大边权 int p=2; while(p>=0 && d[p]==d[3]) p--; d2[u][i]=(p==-1?-INF:d[p]); //次大边权 } for(int i=h[u]; i; i=ne[i]){ int v=to[i],w=ww[i]; if(v!=f){ d1[v][0]=w; dfs(v,u); } } } int lca(int u,int v){ //倍增求lca if(dep[u]<dep[v]) swap(u,v); for(int i=17;i>=0;i--)if(dep[fa[u][i]]>=dep[v]) u=fa[u][i]; if(u==v) return u; for(int i=17; i>=0; i--)if(fa[u][i]!=fa[v][i]) u=fa[u][i],v=fa[v][i]; return fa[u][0]; } int query(int u,int v,int w){ //倍增求小于w的最大边权 int res=-INF; for(int i=17; i>=0; i--){ if(dep[fa[u][i]]>=dep[v]){ if(w>d1[u][i]) res=max(res,d1[u][i]); else if(w==d1[u][i]) res=max(res,d2[u][i]); u=fa[u][i]; } } return res; } }T; int main(){ scanf("%d%d",&n,&m); for(int i=1,u,v,w; i<=m; i++){ scanf("%d%d%d",&u,&v,&w); e[i]={u,v,w}; } kruskal(); T.dfs(1,0); ll ans=1e18; for(int i=1; i<=m; i++)if(!used[i]){ //非树边 auto [u,v,w]=e[i]; int l=T.lca(u,v); ll w1=T.query(u,l,w),w2=T.query(v,l,w); ans=min(ans,sum-max(w1,w2)+w); } printf("%lld\n",ans); } -
0
#include <bits/stdc++.h> using namespace std; typedef long long LL; const int N=1e5+5,M=3e5+5; const int inf=0x7fffffff; vector<pair<int,int>> G[N]; struct edge{int x,y,c;} e[M];int vis[M]; bool cmp(edge n1,edge n2){return n1.c < n2.c;} int n,m,fa[N];LL ans; int findfa(int x){ return (fa[x]==x)?x:fa[x]=findfa(fa[x]);} void kruskal() { for(int i=1;i<=n;i++) fa[i]=i; sort(e+1,e+m+1,cmp);memset(vis,0,sizeof(vis)); ans=0; for(int i=1,t=0;i<=m;i++) { int x=e[i].x,y=e[i].y,c=e[i].c; int tx=findfa(x),ty=findfa(y); if(tx!=ty) { fa[tx]=ty; ans=ans+c;vis[i]=1; G[x].push_back({y,c}),G[y].push_back({x,c}); if(++t==n-1) return; } } } int D,dep[N],f[N][20],g[N][20][2]; void dfs(int x,int fa,int c) { dep[x]=dep[fa]+1; f[x][0]=fa; g[x][0][0]=c; g[x][0][1]=-inf; for(int i=1;i<=D;i++) { f[x][i]=f[f[x][i-1]][i-1]; g[x][i][0]=max(g[x][i-1][0],g[f[x][i-1]][i-1][0]); if(g[x][i-1][0]==g[f[x][i-1]][i-1][0]) g[x][i][1]=max(g[x][i-间][1],g[f[x][i-1]][i-1][1]); if(g[x][i-1][0]<g[f[x][i-1]][i-1][0]) g[x][i][1]=max(g[x][i-间][0],g[f[x][i-1]][i-1][1]); if(g[x][i-1][0]>g[f[x][i-1]][i-1][0]) g[x][i][1]=max(g[x][i-间][1],g[f[x][i-1]][i-1][0]); } for(auto i:G[x]) { int y=i.first,c=i.second;if(y==fa) continue; dfs(y,x,c); } } int lca(int x,int y) { if(dep[x]<dep[y]) swap(x,y); for(int i=D;i>=0;i--) if(dep[f[x][i]]>=dep[y]) x=f[x][i]; if(x==y) return x; for(int i=D;i>=0;i--) if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i]; return f[x][0]; } int get_max(int x,int y,int c) { int res=-inf; for(int i=D;i>=0;i--) if(dep[f[x][i]]>=dep[y]) { if(c>g[x][i][0]) res=max(res,g[x][i][0]); if(c==g[x][i][0]) res=max(res,g[x][i][1]); x=f[x][i]; } return res; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].c); kruskal(); dep[0]=0;D=log2(n);dfs(1,0,0); LL t=inf; for(int i=1;i<=m;i++) if(!vis[i]) { int x=e[i].x,y=e[i].y,c=e[i].c; int p=lca(x,y); LL tt=max(get_max(x,p,c),get_max(y,p,c)); t=min(t,c-tt); } printf("%lld",ans+t);return 0; }
- 1
信息
- ID
- 3642
- 时间
- 1000ms
- 内存
- 512MiB
- 难度
- 10
- 标签
- 递交数
- 7
- 已通过
- 4
- 上传者