AcWing1148 秘密的奶牛运输(次小生成树)
先求一遍最小生成树,再枚举每一个非树边,如果能替换最大值就替换,如果相等则替换次大值
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=510,M=10010; int h[N], e[N * 2], w[N * 2], ne[N * 2], idx; struct node{ int a,b,c,f; bool operator<(const node &t) const{ return c<t.c; } }ei[M]; int p[N]; int d1[N][N],d2[N][N]; void dfs(int u,int fa,int m1,int m2,int d1[],int d2[]){ d1[u]=m1,d2[u]=m2; int i; for(i=h[u];i!=-1;i=ne[i]){ int j=e[i]; if(j==fa) continue; int tmp1=m1,tmp2=m2; if(tmp1<w[i]) tmp2=tmp1,tmp1=w[i]; else if(tmp2<w[i]&&w[i]<tmp1) tmp2=w[i]; dfs(j,u,tmp1,tmp2,d1,d2); } } int find(int x){ if(x!=p[x]) p[x]=find(p[x]); return p[x]; } void add(int a,int b,int c){ e[idx]=b,ne[idx]=h[a],w[idx]=c,h[a]=idx++; } int main(){ int n,m; int i; cin>>n>>m; memset(h,-1,sizeof h); for(i=0;i<m;i++){ int a,b,c; cin>>a>>b>>c; ei[i]=node{a,b,c,0}; } for(i=1;i<=n;i++) p[i]=i; sort(ei,ei+m); ll ans=0; for(i=0;i<m;i++){ int a=ei[i].a,b=ei[i].b,c=ei[i].c; int pa=find(a),pb=find(b); if(pa!=pb){ p[pa]=pb; ei[i].f=1; add(a,b,c); add(b,a,c); ans+=c; } } ll res=1e18; for(i=1;i<=n;i++) dfs(i,-1,-1e9,-1e9,d1[i],d2[i]); for(i=0;i<m;i++){ if(!ei[i].f){ ll t; int a=ei[i].a,b=ei[i].b,c=ei[i].c; if(c>d1[a][b]) t=ans+c-d1[a][b]; else t=ans+c-d2[a][b]; res=min(res,t); } } cout<<res<<endl; }
没有人不辛苦,只有人不喊疼