AcWing算法提高课 次小生成树

次小生成树有性质:

 

 例题:https://www.acwing.com/problem/content/1150/

代码:

复制代码
#include<bits/stdc++.h>

#define fore(x,y,z) for(LL x=(y);x<=(z);x++)
#define forn(x,y,z) for(LL x=(y);x<(z);x++)
#define rofe(x,y,z) for(LL x=(y);x>=(z);x--)
#define rofn(x,y,z) for(LL x=(y);x>(z);x--)
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second

using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
typedef pair<LL,LL> PLL;
typedef pair<int,PII> PIII;
int n,m;
const int N=510;
int dis[N][N];
int dis2[N][N];
int p[N];
vector<int> adj[N];
vector<int> cost[N];
vector<PIII> edges;
vector<int> mark;
int find(int x)
{
    if(p[x]!=x) p[x]=find(p[x]);
    return p[x];
}
void DFS(int u,int max_w,int max_w2,int pa,int o)
{
    dis[o][u]=max_w;
    dis2[o][u]=max_w2;
    //cout<<o<<u<<dis[o][u]<<endl;
    auto &nxts=adj[u];
    auto &costs=cost[u];
    for(int i=0;i<nxts.size();i++)
    {
        int nxt=nxts[i];
        int c=costs[i];
        int t1,t2;
        if(c>max_w)
        {
            t1=c;
            t2=max_w;
        }
        else if(c<max_w&&c>max_w2)
        {
            t1=max_w;
            t2=c;
        }

        if(nxt!=pa)
        {
            DFS(nxt,t1,t2,u,o);
        }
    }
}
void YD()
{
    cin>>n>>m;
    int a,b,c;
    while (m -- )
    {
        cin>>a>>b>>c;
        edges.push_back({c,{a,b}});

    }
    sort(edges.begin(),edges.end());
    for(int i=1;i<=n;i++) p[i]=i;
    LL sum=0;
    for(auto &[w,ij]:edges)
    {
        int i=ij.fi,j=ij.se;
        int pi=find(i);
        int pj=find(j);
        if(pi!=pj)
        {
            p[pi]=pj;
            sum+=w;
            adj[i].push_back(j);
            cost[i].push_back(w);
            adj[j].push_back(i);
            cost[j].push_back(w);
            mark.push_back(1);
        }
        else
        {
            mark.push_back(0);
        }
    }
    //cout<<sum<<endl;
    for(int i=1;i<=n;i++)
    {
        DFS(i,0,0,0,i);
    }
    LL res=1e15;
    for(int i=0;i<edges.size();i++)
    {

        if(!mark[i])
        {
            int a=edges[i].se.fi;
            int b=edges[i].se.se;
            int w=edges[i].fi;
            if(w>dis[a][b])
            {
                res=min(res,sum+w-dis[a][b]);

            }
            else if(w>dis2[a][b]&&dis2[a][b]!=0)
            {
                res=min(res,sum+w-dis2[a][b]);
            }
        }
    }
    cout<<res<<endl;
}
 
int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int T=1;
    //cin >> T;
    while (T--)
    {
        YD();
    }
    return 0;
}
View Code
复制代码

注意 获取严格次小生成树需要记录次大值(树上),非严格次小可以只记录最大值(树上)。

posted @   80k  阅读(23)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
点击右上角即可分享
微信分享提示