首页 > 其他分享 >P5631 最小mex生成树

P5631 最小mex生成树

时间:2024-12-06 12:15:25浏览次数:3  
标签:le int mid 最小 mex 答案 P5631 我们

P5631 最小mex生成树

题目背景

这是一道经典题。

题目描述

给定 \(n\) 个点 \(m\) 条边的无向连通图,边有边权。

设一个自然数集合 \(S\) 的 \(\text{mex}\) 为:最小的、没有出现在 \(S\) 中的自然数。

现在你要求出一个这个图的生成树,使得其边权集合的 \(\text{mex}\) 尽可能小。

【数据范围】

  • 对于 \(100\%\) 的数据,\(1\le n \le 10^6\),\(1\le m \le 2\times 10^6,0\le w \le 10^5\)。

Solution:

非常人类智慧的经典题,首先我们来考虑如何判断答案是否合法,假设我们现在钦定了一个答案ans,那么我们就应该把所有边权不为ans的边全部加入这个图中跑一遍生成树

但是我们发现如果一个个去枚举答案的话那么时间复杂度将变为\(O(n*w*logn)\)这显然是我们所不能接受的,但是答案貌似又不满足单调性

我们考虑如何优化“枚举答案”这一十分不优秀的过程:我们可以思考这个算法暴力在哪:每一次换一个答案就要重新跑一边生成树,这显然是十分不优秀的,我们考虑优化这一过程:

我们考虑进行分治:solve(l,r)表示将所有边权在\([0,l-1]\)U\([r+1,inf]\)的边全部加入了图中。对于结束状态:l==r,如果当前的图是一棵树,那么答案成立,直接输出并结束程序,否则普通return ;

然后我们对于一个区间[l,r]:先将所有满足\(w \in [mid+1,r]\)的边加入图中,然后先递归左子树(为了最小化答案)。
如果程序没结束,我们先删除 \(w \in [mid+1,r]\)的所有边。我们再将\(w \in [l,mid]\)的边加入图中,递归右子树

但是有一点要特别注意的:我们在加边的时候显然不能直接便利整个边集,不然我们的时间复杂度还是会退化到\(O(n*w*logn)\)

注意到:我们在处理solve(l,r)这一函数时,已经完成了所有满足 \(w \in [0,l-1] or [r+1,inf],\)的边的添加.
所以我们多记一个参数:pos表示第一个满足\(l \le w\)的位置。这样就可以保证我们遍历所有边的复杂度均摊完是\(O(nlogn)\)的

然后再补充一下删除操作:由于我们要做删除,所以在写并查集时不能路径压缩(显然),然后对于每个删除就将
siz[fa]-=siz[x],fa[x]=x就好了,同时要注意的是,我们每次只能删除在本区间[l,r]内添加的边,所以在储存时切不可混用容器

然后这题就愉快的做完了

Code:

#include<bits/stdc++.h>
const int N=2e6+5;
using namespace std;
struct Edge{
    int u,v,w;
    bool operator <(const Edge &e)const{
        return w<e.w;
    }
}q[N];
int n,m;
int fa[N],siz[N];
int find(int x){return fa[x]==x ? fa[x] : find(fa[x]);}
int merge(int x,int y)
{
    int fx=find(x),fy=find(y);
    if(fx==fy)return 0;
    if(siz[fx]<siz[fy])swap(fx,fy);
    fa[fy]=fx,siz[fx]+=siz[fy];return fy;
}
void split(int x)
{
    siz[fa[x]]-=siz[x];
    fa[x]=x;
}
void ANS(int x)
{
    printf("%d\n",x);
    exit(0);
}
void solve(int l,int r,int pos)
{
    if(l==r)
    {
        if(siz[find(1)]==n)ANS(l);
        return ;
    }
    vector<int> E;
    int mid=l+r>>1,x=0;
    for(int i=pos;i<=m&&q[i].w<=r;i++)
    {
        if((q[i].w>mid)&&(x=merge(q[i].u,q[i].v)))
        E.push_back(x);
    }
    solve(l,mid,pos);
    for(int i=E.size()-1;~i;i--){split(E[i]);}E.clear();
    for(int &i=pos;i<=m&&q[i].w<=mid;i++)
    {
        if(x=merge(q[i].u,q[i].v))
        E.push_back(x);
    }
    solve(mid+1,r,pos);
    for(int i=E.size()-1;~i;i--){split(E[i]);}E.clear();
}
void work()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++){fa[i]=i,siz[i]=1;}
    for(int i=1,u,v,w;i<=m;i++)
    {
        scanf("%d%d%d",&u,&v,&w);
        q[i]=(Edge){u,v,w};
    }
    sort(q+1,q+1+m);
    solve(0,q[m].w+1,1);
}
int main()
{
    //freopen("P5631.in","r",stdin);
    //freopen("P5631.out","w",stdout);
    work();
    return 0;
}

标签:le,int,mid,最小,mex,答案,P5631,我们
From: https://www.cnblogs.com/LG017/p/18590457

相关文章

  • P6192 【模板】最小斯坦纳树
    题目描述:题目给定一张图上的几个关键点,要求我们用最小的边权将这些点连起来不难发现,最后连出来的答案一定是一棵树:如果有环的话,将环优化掉一定更好我们考虑dp:对于一个节点x钦定它是这颗树的根。记dp[rt][s]表示以rt为根,关键点被链接的状态为s时的最小花费则在最短路中......
  • 【知识】字符串 最小表示法
    问题描述:最小表示法是字符串\(S\)循环同构的所有字符串中,字典序最小的串是哪个。最小表示法:考虑对于一对字符串\(A,B\),它们在原字符串\(S\)中的起始位置分别为\(i,j\),且它们的前\(k\)个字符均相同,即\[S[i\cdotsi+k-1]=S[j\cdotsj+k-1]\]不妨先考虑\(S[i+k]>......
  • 最小成本,最快速度 离线安装esp32/esp8266 arduino ide
    之前担任学校的实验室负责人,每届带新生都会给学弟学妹安装esp32/8266的编译环境,如果不采用离线安装的方式,步骤是繁琐的,而且很容易出错,可能得安装个两三天.  本身arduinoide是给初学者使用的,一个敲门砖,没必要在此浪费过多时间,下面是我分享的安装方法安装流程尽可能......
  • vue中json对象数组求最大、最小、合计方法
    可以使用Array.reduce()方法来求最大、最小、合计值。示例代码如下://假设有以下json对象数组letarr=[{name:'tina',score:90},{name:'tom',score:80},{name:'john',score:70},{name:'jane',score:85}]//求最高分letmaxScor......
  • AI绘画 Stable Diffusion 【真人模型】:一款适合画中国女孩的国产真人大模型MexxL_LCM2
    目前StableDiffusion大模型中,真人模型可谓,百发齐放,精彩纷呈,令人目眩神迷。真人模型充分展现着栩栩如生的美态与神采。逼真的面部表情、流畅自然的动作,融合了真实和[虚拟的]完美之美。然而很多真人大模型都是参照着西方女性的特征,在绘制中国女性方面,还略微逊色。今天就和大......
  • 人形机器人:从零开发人形机器人 —— 某开源的个人DIY版本(2500元DIY世界最小,开源端到端
    相关介绍:https://www.bilibili.com/video/BV1in6PY7E1B......
  • [数组滑动窗口] 0995. K连续位的最小翻转次数
    文章目录1.题目链接2.题目大意3.示例4.解题思路5.参考代码1.题目链接https://leetcode.cn/problems/minimum-number-of-k-consecutive-bit-flips/description/2.题目大意描述:给定一个仅包含0和1的数组numsnums,再给定一个整数k。进行一次k位翻......
  • 如何使用css实现跨浏览器的最小高度?
    CSS中实现跨浏览器兼容的最小高度,曾经是一个令人头疼的问题,但现在已经有了相对简单的解决方案。以下几种方法可以实现:1.min-height属性(推荐):这是现代浏览器中最直接和推荐的方法。min-height属性直接设置元素的最小高度。大多数现代浏览器都支持这个属性,包括IE7及以上......
  • 【双堆懒删除】codeforces 1294 D. MEX maximizing
    前言双堆懒删除当需要维护若干元素中的最大值(或最小值)时,可以用一个堆维护,但是堆只擅长处理堆顶元素,对堆中任意元素的处理就束手无策了。此时,可以引入另外一个堆,我们定义原来的堆为保存堆\(ex\),新的堆为懒删除堆\(de\)。那么当需要从保存堆中删除任意一个元素时,可以先将元素放......
  • 最小表示法
    最小表示法感觉这是一个很冷门的算法?遇到的题不多,但是很有趣。什么是最小表示法用来求一个字符串或数列,循环得到的串或数列,字典序最小的是哪个。如何求最小表示法定义两个指针\(i\)和\(j\),初始时指向\(0\)和\(1\)。维护一个\(k\),表示\(i\)开头的子串和\(j\)开......