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;
} 
View Code

 

posted @ 2020-05-06 20:58  朝暮不思  阅读(180)  评论(0编辑  收藏  举报