1 条题解
-
0
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N = 3e5+7,M = 3e5 + 7,MM = 3e5+7; const ll INF = 0x7ffffffffff;; int n,m; ll sum; int cnt,head[MM],ver[MM],nex[MM],edge[MM]; int tree[MM],pre[N],ppre[N][23],depth[N],lg[N]; ll maxf[N][23],minf[N][23];//这两个要和ans 作比较,所以用ll struct E{ int from,to,w; E(){} E(int from,int to,int w) : from(from),to(to),w(w){} bool operator < (const E &b)const{ return w < b.w; } }e[M]; void add(int x,int y,int w){ ver[++cnt] = y; nex[cnt] = head[x]; edge[cnt] = w; head[x] = cnt; } int find(int x){ return x == pre[x] ? x : pre[x] = find(pre[x]); } void read(){ scanf("%d%d",&n,&m); for(int i=1;i <= m;i ++) scanf("%d%d%d",&e[i].from,&e[i].to,&e[i].w); for(int i=0; i < N; i++) pre[i] = i; } void work1(){ sort(e+1,e+m+1); for(int i=1;i <= m;i ++){ int x = e[i].from,y = e[i].to,w = e[i].w; int fx = find(x), fy = find(y); if(fx != fy){ pre[fx] = fy; sum += w; add(x,y,w); add(y,x,w); tree[i] = 1; } } } void dfs(int f,int fa,int w){ depth[f] = depth[fa] + 1; ppre[f][0] = fa; minf[f][0] = -INF; maxf[f][0] = w; for(int i=1; (1<<i) <= depth[f];i++){ ppre[f][i] = ppre[ppre[f][i-1]][i-1]; maxf[f][i] = max(maxf[f][i-1],maxf[ppre[f][i-1]][i-1]); minf[f][i] = max(minf[f][i-1],minf[ppre[f][i-1]][i-1]);//这里分清次小关系 if(maxf[f][i-1] > maxf[ppre[f][i-1]][i-1]) minf[f][i] = max(minf[f][i],maxf[ppre[f][i-1]][i-1]); else if(maxf[f][i-1] < maxf[ppre[f][i-1]][i-1]) minf[f][i] = max(minf[f][i],maxf[f][i-1]); } for(int i=head[f]; i ; i=nex[i]){ int y = ver[i],w = edge[i]; if(y != fa){ dfs(y,f,w); } } } int lca(int x,int y){ if(depth[x] < depth[y]) swap(x,y); while(depth[x] > depth[y]) x = ppre[x][lg[depth[x]-depth[y]] -1]; if(x==y) return x; for(int i = lg[depth[x]]-1; i>=0; i--){ if(ppre[x][i] != ppre[y][i]) x= ppre[x][i],y = ppre[y][i]; } return ppre[x][0]; } ll qmax(int x,int y,int maxx){ ll ans = -INF; for(int i = lg[depth[x]]-1;i>=0;i--){ if(depth[ppre[x][i]]>=depth[y]){ if(maxx != maxf[x][i]) ans = max(ans,maxf[x][i]); else ans = max(ans,minf[x][i]); x = ppre[x][i]; } } return ans; } void work2(){ for(int i=1;i <= n;i++) lg[i] = lg[i-1] + (1<<lg[i-1]==i); dfs(1,0,0); ll ans = INF; for(int i = 1;i <= m;i++){ if(tree[i]) continue; int x = e[i].from,y = e[i].to,w = e[i].w; int lc = lca(x,y); ll maxx = qmax(x,lc,w); ll maxv = qmax(y,lc,w); ans = min(ans,sum-max(maxx,maxv)+w);//找到到公共父亲节点路径中最大的那条,替换到非树边。 } printf("%lld\n",ans); } int main(){ read(); work1(); work2(); return 0; }
- 1
信息
- ID
- 949
- 时间
- 1000ms
- 内存
- 512MiB
- 难度
- (无)
- 标签
- (无)
- 递交数
- 0
- 已通过
- 0
- 上传者