次小生成树,顾名思义和次短路的思路似乎很类似呀,
于是就先写了个kruskal(prim不会)跑出最小生成树,给所有路径打标记,再逐个跑最小生成树取大于最小生成树的最小值 50分
#include<bits/stdc++.h> #define rep(i,x,y) for(register int i=x;i<=y;i++) #define dec(i,x,y) for(register int i=x;i>=y;i--) #define ll long long using namespace std; const int N=100050; const int M=300050; const int inf=0x3f3f3f3f; inline int read(){ int x=0,f=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} return x*f;} int n,m,u,v,w,fa[N],ok[N],k; struct node{int u,v,w;}e[M<<1]; bool cmp(node a,node b){return a.w<b.w;} inline int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);} int kruskal(){ int cnt=n,ans=0; rep(i,1,n) fa[i]=i; for(int i=1;i<=m;i++){ if(cnt==1) break; if(ok[i]==0){ int xx=find(e[i].u),yy=find(e[i].v); if(xx!=yy) fa[yy]=xx,cnt--,ans+=e[i].w;} }return ans;} int main(){ n=read();m=read(); rep(i,1,m){ u=read();v=read();w=read(); e[i]=(node){u,v,w};} sort(e+1,e+1+m,cmp); //ok =0代表 int ans=inf,mi=kruskal(); for(int i=1;i<=m;i++){ ok[i]=1;k=kruskal(); if(k>mi) ans=min(ans,k);ok[i]=0;} printf("%d\n",ans); return 0; }
100分(啥时候得再复习一下,不看题解不会做系列,ganxiehzwercode,啥时候再拿出来重新写一写)
对于非最小生成树上的路径,其u,v加入后(可能)形成一个环,分别从u.v到lca寻找最大及次大路径,若最大路径不等于(其实就是小于)非生成树边,记录这个最小增量,
相等则取次小边,防止出现 次小==最小
#include<bits/stdc++.h> #define rep(i,x,y) for(register int i=x;i<=y;i++) #define N 100001 #define M 300001 #define inf 0x7fffffff #define ll long long using namespace std; int n,m,tot,cnt,mn=inf;ll ans; int f[N],head[N],dep[N],fa[N][17],d1[N][17],d2[N][17]; struct data{int x,y,v;bool sel;}a[M]; struct edge{int to,next,v;}e[N<<1]; bool cmp(data a,data b){return a.v<b.v;} void insert(int u,int v,int w){ e[++cnt].to=v;e[cnt].next=head[u];e[cnt].v=w;head[u]=cnt; e[++cnt].to=u;e[cnt].next=head[v];e[cnt].v=w;head[v]=cnt;} inline int find(int x){return x==f[x]?x:f[x]=find(f[x]);} void dfs(int u,int f){ for(int i=1;i<=16;i++){ if(dep[u]<(1<<i))break; fa[u][i]=fa[fa[u][i-1]][i-1]; d1[u][i]=max(d1[u][i-1],d1[fa[u][i-1]][i-1]); if(d1[u][i-1]==d1[fa[u][i-1]][i-1]) d2[u][i]=max(d2[u][i-1],d2[fa[u][i-1]][i-1]); else d2[u][i]=min(d1[u][i-1],d1[fa[u][i-1]][i-1]), d2[u][i]=max(d2[u][i],max(d2[u][i-1],d2[fa[u][i-1]][i-1])); }for(int i=head[u];i;i=e[i].next){ int v=e[i].to; if(v==f) continue; fa[v][0]=u; d1[v][0]=e[i].v; dep[v]=dep[u]+1; dfs(v,u); } } int lca(int x,int y){ if(dep[x]<dep[y])swap(x,y); int t=dep[x]-dep[y]; for(int i=0;i<=16;i++) if((1<<i)&t)x=fa[x][i]; for(int i=16;i>=0;i--) if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i]; if(x==y)return x; return fa[x][0];} void cal(int x,int f,int v){ int mx1=0,mx2=0; int t=dep[x]-dep[f]; for(int i=0;i<=16;i++) if(t&(1<<i)){ if(d1[x][i]>mx1){ mx2=mx1; mx1=d1[x][i];} mx2=max(mx2,d2[x][i]); x=fa[x][i]; } if(mx1!=v)mn=min(mn,v-mx1); else mn=min(mn,v-mx2);} void solve(int t,int v){ int x=a[t].x,y=a[t].y,f=lca(x,y); cal(x,f,v);cal(y,f,v);} int main(){ scanf("%d%d",&n,&m); rep(i,1,n) f[i]=i; rep(i,1,m) scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].v); sort(a+1,a+m+1,cmp); rep(i,1,m){ int xx=find(a[i].x),yy=find(a[i].y); if(xx!=yy){ f[xx]=yy; ans+=a[i].v; a[i].sel=1; insert(a[i].x,a[i].y,a[i].v); tot++;if(tot==n-1)break;} }dfs(1,0); rep(i,1,m) if(!a[i].sel)solve(i,a[i].v); printf("%lld",ans+mn); return 0; }