《P4180 [BJWC2010]严格次小生成树》
好久没码题了,码力好像有点下降。
这题有结论可知:枚举没条不在最小生成树上的边,将这条边连上成环,那么就可以去掉环上的最长边(除了新加的这条)。
因为这里是严格次小树,那么最长边就不能和这条新边相等,显然这条最长边只能 <= 新边,如果大于的话,那么最小生成树就可以有更小的。
倍增维护最小值和次小值,如果光维护最小值,那么可能最长边 == 新边,维护次小值就能避免这点。
u 写成了 i调试了n久。
#include<bits/stdc++.h> using namespace std; typedef long long LL; typedef pair<int,int> pii; const int N = 1e5 + 5; const int M = 3e5 + 5; const LL Mod = 1e9 + 7; #define pi acos(-1) #define INF 1e18 #define dbg(ax) cout << "now this num is " << ax << endl; namespace FASTIO{ inline LL read(){ LL x = 0,f = 1;char c = getchar(); while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();} while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();} return x*f; } } using namespace FASTIO; int n,m,fa[N],f[N][20],dep[N],lg[N],tag[N];//ff - father LL Mx[N][20],Sx[N][20]; struct Edge{ int st,to,dis; bool operator < (const Edge a)const{ return dis < a.dis; } }e[M]; vector<Edge> G[N]; void init(){ for(int i = 1;i < N;++i) lg[i] = lg[i - 1] + ((1 << lg[i - 1]) == i); } int Find(int x){ return x == fa[x] ? x : fa[x] = Find(fa[x]); } void dfs(int u,int ffa,int len){ dep[u] = dep[ffa] + 1; f[u][0] = ffa,Mx[u][0] = len,Sx[u][0] = -INF; for(int i = 1;i <= lg[dep[u]];++i) { f[u][i] = f[f[u][i - 1]][i - 1]; Mx[u][i] = max(Mx[u][i - 1],Mx[f[u][i - 1]][i - 1]); Sx[u][i] = max(Sx[u][i - 1],Sx[f[u][i - 1]][i - 1]); if(Mx[u][i - 1] > Mx[f[u][i - 1]][i - 1]) Sx[u][i] = max(Sx[u][i],Mx[f[u][i - 1]][i - 1]); else if(Mx[u][i - 1] < Mx[f[u][i - 1]][i - 1]) Sx[u][i] = max(Sx[u][i],Mx[u][i - 1]); } for(auto v : G[u]) if(v.to != ffa) dfs(v.to,u,v.dis); } LL solve(int x,int y,int up){ if(dep[x] < dep[y]) swap(x,y); LL ans = -1; while(dep[x] > dep[y]){ int step = lg[dep[x] - dep[y]] - 1; if(Mx[x][step] != up) ans = max(ans,Mx[x][step]); else ans = max(ans,Sx[x][step]); x = f[x][step]; } if(x == y) return ans; for(int i = lg[dep[x]] - 1;i >= 0;--i){ if(f[x][i] != f[y][i]){ if(Mx[x][i] != up) ans = max(ans,Mx[x][i]); else ans = max(ans,Sx[x][i]); if(Mx[y][i] != up) ans = max(ans,Mx[y][i]); else ans = max(ans,Sx[y][i]); x = f[x][i],y = f[y][i]; } } if(x == y) return ans; if(Mx[x][0] != up) ans = max(Mx[x][0],ans); if(Mx[y][0] != up) ans = max(Mx[y][0],ans); return ans; } int main() { init(); n = read(),m = read(); for(int i = 1;i <= n;++i) fa[i] = i; LL sum = 0; for(int i = 1;i <= m;++i){ e[i].st = read(),e[i].to = read(),e[i].dis = read(); } sort(e + 1,e + m + 1); for(int i = 1;i <= m;++i){ int xx = Find(e[i].st),yy = Find(e[i].to); if(xx != yy){ fa[xx] = yy; G[e[i].st].push_back(Edge{e[i].st,e[i].to,e[i].dis}); G[e[i].to].push_back(Edge{e[i].to,e[i].st,e[i].dis}); tag[i] = 1; sum += e[i].dis; } } dfs(1,0,0); LL ans = INF; for(int i = 1;i <= m;++i){ if(tag[i] == 1) continue; LL temp = solve(e[i].st,e[i].to,e[i].dis); //printf("x is %d y is %d tmp is %lld\n",e[i].st,e[i].to,temp); ans = min(ans,sum - temp + e[i].dis); } printf("%lld\n",ans); system("pause"); return 0; }