严格次小生成树[BJWC2010]

题目

维护环内最大值与严格次大值

与未放入最小生成树的边枚举加入

#include<bits/stdc++.h>
#define re return
#define dec(i,l,r) for(ll i=l;i>=r;--i)
#define inc(i,l,r) for(ll i=l;i<=r;++i)

typedef long long ll;

using namespace std;
template<typename T>inline void rd(T&x)
{
    char c;bool f=0;
    while((c=getchar())<‘0‘||c>‘9‘)if(c==‘-‘)f=1;
    x=c^48;
    while((c=getchar())>=‘0‘&&c<=‘9‘)x=x*10+(c^48);
    if(f)x=-x;
}

const int maxn=100005,maxm=300005;
ll n,m,k=1,hd[maxn],deep[maxn];
ll max1[maxn][21],max2[maxn][21],fa[maxn][21];
ll vis[maxm],f[maxn];
ll sum,ans=999999999999999999;

struct node
{
    ll fr,to,nt,val;
    bool operator<(node p)const
    {
        re val<p.val;
    }
}e[maxm],e1[maxn<<1];

inline void add1(int x,int y,int z)
{
    e1[++k].to=y;e1[k].nt=hd[x];hd[x]=k;e1[k].val=z;
    e1[++k].to=x;e1[k].nt=hd[y];hd[y]=k;e1[k].val=z;
}    

inline void dfs(int x)
{
    deep[x]=deep[fa[x][0]]+1;
    for(int i=0;fa[fa[x][i]][i];++i)
    {
        fa[x][i+1]=fa[fa[x][i]][i];
        if(max1[x][i]==max1[fa[x][i]][i])
        {
            max1[x][i+1]=max1[x][i];
            max2[x][i+1]=max(max2[x][i],max2[fa[x][i]][i]);
        }
        else if(max1[x][i]>max1[fa[x][i]][i])
        {
            max1[x][i+1]=max1[x][i];
            max2[x][i+1]=max(max1[fa[x][i]][i],max2[x][i]);
        }
        else
        {
            max1[x][i+1]=max1[fa[x][i]][i];
            max2[x][i+1]=max(max1[x][i],max2[fa[x][i]][i]);
        }
    } 

    for(ll i=hd[x];i;i=e1[i].nt)
    {
        ll v=e1[i].to;
        if(v==fa[x][0])continue;
        fa[v][0]=x;
        max1[v][0]=e1[i].val;
        max2[v][0]=-2147483647;
        dfs(v);
    }
}

inline ll find(ll x)
{
    re x==f[x]?x:f[x]=find(f[x]);
}
int main()
{

//    freopen("in.txt","r",stdin);
freopen("tree8.in","r",stdin);

    ll x,y,z; 

    rd(n),rd(m);
    inc(i,1,n)f[i]=i;

    inc(i,1,m)
    {
        rd(x),rd(y),rd(z);
        e[i]=(node){x,y,0,z};
    }

    sort(e+1,e+m+1);

    k=0;
    ll cnt=0;
    inc(i,1,m)
    {
        x=find(e[i].to),y=find(e[i].fr);
        if(x!=y)
        {
            add1(e[i].to,e[i].fr,e[i].val);
            sum+=e[i].val;
            vis[i]=1;
            f[x]=y;
            ++cnt;
            if(cnt==n-1)break;
        }
    }

    dfs(1);

    inc(j,1,m)
    if(!vis[j])
    {
        x=e[j].to;y=e[j].fr;
//--------------------------------------------------------------------------------
        ll d1=0,d2=0;
        if(deep[x]<deep[y])swap(x,y);

        dec(i,20,0)
        if(deep[fa[x][i]]>=deep[y])
        {
            if(max1[x][i]>d1)
            {
                d2=max(d1,max2[x][i]);
                d1=max1[x][i];
            }
            else if(max1[x][i]!=d1)
                 d2=max(d2,max1[x][i]);

            x=fa[x][i];
        }
        if(x!=y)
        {
            dec(i,20,0)
            if(fa[x][i]!=fa[y][i])
            {
                if(max1[x][i]>d1)
                {
                    d2=max(d1,max2[x][i]);
                    d1=max1[x][i];
                }
                else if(max1[x][i]!=d1)
                     d2=max(d2,max1[x][i]);

                if(max1[y][i]>d1)
                {
                    d2=max(d1,max2[y][i]);
                    d1=max1[y][i];
                }
                else if(max1[y][i]!=d1)
                     d2=max(d2,max1[y][i]);
                x=fa[x][i];y=fa[y][i];
            }
            if(max1[x][0]>d1)
            {
                d2=d1;
                d1=max1[x][0];
            }
            else if(max1[x][0]!=d1)
                d2=max(d2,max1[x][0]);
            if(max1[y][0]>d1)
            {
                d2=d1;
                d1=max1[y][0];
            }
            else if(max1[y][0]!=d1)
                d2=max(d2,max1[y][0]);

        }
//-----------------------------------------------------------------------------------------------------
        if(d1==e[j].val)ans=min(ans,sum+e[j].val-d2);
        else ans=min(ans,sum+e[j].val-d1);
    }

    printf("%lld",ans);
    re 0;
}

原文地址:https://www.cnblogs.com/lsyyy/p/11417366.html

时间: 2024-10-10 01:04:41

严格次小生成树[BJWC2010]的相关文章

Luogu P4180 【模板】严格次小生成树[BJWC2010]

P4180 [模板]严格次小生成树[BJWC2010] 题意 题目描述 小\(C\)最近学了很多最小生成树的算法,\(Prim\)算法.\(Kurskal\)算法.消圈算法等等.正当小\(C\)洋洋得意之时,小\(P\)又来泼小\(C\)冷水了.小\(P\)说,让小\(C\)求出一个无向图的次小生成树,而且这个次小生成树还得是严格次小的,也就是说:如果最小生成树选择的边集是\(E_M\),严格次小生成树选择的边集是\(E_S\),那么需要满足:(\(value(e)\)表示边\(e\)的权值)\

洛谷 P4180 【模板】严格次小生成树[BJWC2010]【次小生成树】

严格次小生成树模板 算法流程: 先用克鲁斯卡尔求最小生成树,然后给这个最小生成树树剖一下,维护边权转点权,维护最大值和严格次大值. 然后枚举没有被选入最小生成树的边,在最小生成树上查一下这条边的两端点的路径上的最长边,如果最长边等于枚举到的边的边权,那么选次长边(没有次长边的话直接跳过),然后在最小生成树的权值上减去路径上最/次长边,加上当前枚举的边的边权 因为如果加入枚举的边的,那么就形成了一个环,需要断开一条边 注意一开始单点次小值赋为0 #include<iostream> #inclu

P4180 【模板】严格次小生成树[BJWC2010]

传送门 次小生成树 那肯定是最小生成树上改一条边(改两条肯定不如只改其中一条小) 那就枚举所有不在最小生成树上的边 考虑如果把此边加入,另一边删除后的情况 考虑要删哪条边后才能保持树的形态,并且总长最小 加入一条边后树就会出现一个环 那么删掉的边要在加入的边连接的两点间的路径上 并且删去的边要尽量大 那就可以用LCA来求出树上两点间路径上的最长边 但是现在还有一个问题,可能删去的边和加入的边一样长 所以还要维护一下次长的边 次长边维护也不难,具体看代码 #include<iostream> #

P4180 严格次小生成树[BJWC2010]

题目链接 https://www.luogu.org/problemnew/show/P4180 题目描述 小C最近学了很多最小生成树的算法,Prim算法.Kurskal算法.消圈算法等等.正当小C洋洋得意之时,小P又来泼小C冷水了.小P说,让小C求出一个无向图的次小生成树,而且这个次小生成树还得是严格次小的,也就是说:如果最小生成树选择的边集是EM,严格次小生成树选择的边集是ES,那么需要满足:(value(e)表示边e的权值) \sum_{e \in E_M}value(e)<\sum_{e

P4180 严格次小生成树[BJWC2010] Kruskal,倍增

题目链接\(Click\) \(Here\). 题意就是要求一个图的严格次小生成树.以前被题面吓到了没敢做,写了一下发现并不难. 既然要考虑次小我们就先考虑最小.可以感性理解到一定有一种次小生成树,可以由最小生成树删一条边再加一条边得到.我们枚举加上去的这一条边,加上去以后原\(mst\)会成为一个基环树,想让它次小就在这个环里找一条最长的边(不包含新加进去的)删掉就好.放在树上来讲,就是找到\(u\)到\(v\)路径上的最大值.这样我们就有了非严格次小生成树. 严格要怎么处理?我们需要排除新加

P4180 【模板】严格次小生成树[BJWC2010](严格次小生成树)

题目链接 题意如题 做法 先做一遍最小生成树 枚举添加每一条非树边的情况,每一次构成一棵基环树,在环上找一条最长边(如果等于该非树边就用环上的严格次小边) 倍增LCA,倍增预处理的时候顺便维护严格次大值和最大值(注意细节) (如果是非严格次小生成树则只需要维护最大值即可) 代码 #include <iostream> #include <cstdio> #include <queue> #include <cstring> #include <algo

【BJWC2010】次小生成树

题目链接:https://www.luogu.com.cn/problem/P4180 题目大意:给定一张含有 \(m\) 条边的无向带权图 , 求出这张图中边权之和严格大于最小生成树的次小生成树的边权之和 solution 笔者太鸽了 , 一连咕了三天 , 因此来补一下前两天的锅 这道题的思路很显然 , 先求出这张图的最小生成树 , 记它的边权之和为\(sum\) , 再考虑剩下的 \(m - n + 1\) 条边 , 如果把第 \(i\) 条, 分别连接\(a_i , b_i\), 权值为\

HDU4081 Qin Shi Huang&#39;s National Road System【Kruska】【次小生成树】

Qin Shi Huang's National Road System Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 3979    Accepted Submission(s): 1372 Problem Description During the Warring States Period of ancient China(4

Ural 1416 Confidential,次小生成树

不严格次小生成树. 注意图可能不连通. #include <cstdio> #include <cstring> #include <algorithm> #include <vector> using namespace std; const int maxn = 505; const int INF = 1e7; bool vis[maxn]; int d[maxn]; int pre[maxn]; int Max[maxn][maxn]; int g[