标签:nbsp turn bzoj include return col lse scanf std
这道题。。。
中间发生了许多曲折离奇的故事。。。
讲出来你可能不信。。
我写了一整天
主要思想为先找到最小生成树,,再拿不属于最小生成树的边替换,,最后可换出次小生成树
#include<cstdio> #include<cmath> #include<cstring> #include<queue> #include<algorithm> #include<iostream> using namespace std; struct my{ int next; int v; int w; }; const int maxn=600000+10; const int maxm=600000+10; struct lmjer{int x,y,w;}; struct node{int fa,a,b;}f[maxn][30]; int adj[maxn],d[maxn],tot,n,m,fa[maxn],out[maxn],t; int vis[maxn]; long long mst; lmjer a[maxm]; my bian[maxm]; queue<int>q; void myinsert(int u,int v,int w){ bian[++tot].v=v; bian[tot].next=adj[u]; bian[tot].w=w; adj[u]=tot; } bool cmp(const lmjer &x,const lmjer &y){ return x.w<y.w; } int getfa(int x){ if(x==fa[x]) return x; return fa[x]=getfa(fa[x]); } void kruskal(){ for (int i=1;i<=n+10000;i++) fa[i]=i; for (int i=1;i<=m;i++){ int x=getfa(a[i].x); int y=getfa(a[i].y); if(x!=y){ mst+=a[i].w; fa[y]=x; myinsert(a[i].x,a[i].y,a[i].w); myinsert(a[i].y,a[i].x,a[i].w); } else out[i]=1; } } node init(int fa,int x,int y){ node p; p.a=x,p.b=y,p.fa=fa; return p; } void calc(node &p,int x){ if(x>p.a) p.b=p.a,p.a=x; if(x>p.b&&x<p.a) p.b=x; } node update(node x,node y){ node p=y; calc(p,x.a); calc(p,x.b); return p; } void bfs(){ for (int i=1;i<=n;i++){ for (int j=0;j<=t;j++){ f[i][j]=init(-1,-1,-1); } } q.push(1); vis[1]=1; while(!q.empty()){ int x=q.front(); q.pop(); for (int i=adj[x];i;i=bian[i].next){ int v=bian[i].v; if(!vis[v]){ vis[v]=1; q.push(v); f[v][0]=init(x,bian[i].w,-1); d[v]=d[x]+1; for (int j=1;j<=t;j++){ int z=f[v][j-1].fa; if(z==-1) break; f[v][j]=update(f[v][j-1],f[z][j-1]); } } } } } node lca(int x,int y){ node temp=init(-1,-1,-1); if(d[x]<d[y]) swap(x,y); for (int i=t;i>=0;i--){ if(d[x]-(1<<i)>=d[y]){ temp=update(temp,f[x][i]); x=f[x][i].fa; } } if(x==y) return temp; for (int i=t;i>=0;i--){ if(f[x][i].fa!=f[y][i].fa){ temp=update(temp,f[x][i]); temp=update(temp,f[y][i]); x=f[x][i].fa; y=f[y][i].fa; } } temp=update(temp,f[x][0]); temp=update(temp,f[y][0]); return temp; } int main(){ // freopen("bzoj1977.in","r",stdin); // freopen("bzoj1977.out","w",stdout); scanf("%d%d",&n,&m); for (int i=1;i<=m;i++){ scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].w); } t=(int)(log(n)/log(2)); sort(a+1,a+1+m,cmp); kruskal(); bfs(); int ans=0x7f7f7f7f; for (int i=1;i<=m;i++){ if(out[i]){ node tmp=lca(a[i].x,a[i].y); if(a[i].w==tmp.a&&tmp.b!=-1) ans=min(ans,a[i].w-tmp.b); if(a[i].w>tmp.a) ans=min(ans,a[i].w-tmp.a); } } cout<<mst+ans<<endl; return 0; }
标签:nbsp turn bzoj include return col lse scanf std
原文地址:https://www.cnblogs.com/lmjer/p/9396340.html