首页 > 其他分享 >最大数量

最大数量

时间:2023-03-01 10:58:29浏览次数:45  
标签:度数 连通 最大 int text leq 条边 数量

最大数量

一个无向图有 $n$ 个点,编号 $1 \sim n$。

这些点之间没有任何边。

给定 $d$ 个需求,编号 $1 \sim d$。

其中,第 $i$ 个需求是让点 $x_i$ 和点 $y_i$ 连通。

需求可能存在重复。

在本题中,你需要依次解决 $d$ 个问题,编号 $1 \sim d$。

其中,第 $i$ 个问题是,请你在图中添加恰好 $i$ 条无向边(不能添加重边和自环),使得:

  1. 前 $i$ 个需求都得到满足。
  2. 所有点中度最大的点的度尽可能大。

对于每个问题,你不需要输出具体方案,你只需要输出度的最大可能值。

注意:

  1. 如果点 $a$ 和点 $b$ 之间存在路径,则称点 $a$ 和点 $b$ 连通。
  2. 图中与点 $a$ 关联的边数,称为点 $a$ 的度。(如果一个点是一条边的端点,则称这个点和这条边关联)
  3. $d$ 个问题之间是相互独立的,每个问题的答案都必须独立计算。

输入格式

第一行包含两个整数 $n,d$。

接下来 $d$ 行,其中第 i 行包含两个整数 $x_i,y_i$,表示第 i 个需求是让点 $x_i$ 和点 $y_i$ 连通。

输出格式

共 $d$ 行,其中第 $i$ 行输出第 $i$ 个问题中,度的最大可能值。

数据范围

前三个测试点满足,$2 \leq n \leq 10$。

所有测试点满足,$2 \leq n \leq 1000$,$1 \leq d \leq n−1$,$1 \leq x_i,y_i \leq n$,$x_i \ne y_i$。

输入样例1:

7 6
1 2
3 4
2 4
7 6
6 5
1 7

输出样例1:

1
1
3
3
3
6

输入样例2:

10 8
1 2
2 3
3 4
1 4
6 7
8 9
8 10
1 4

输出样例2:

1
2
3
4
5
5
6
8

 

解题思路

  这题读了半天都不知道在说什么,对于第$i$个问题恰好添加$i$条边,一直不知道是指在第$i$个问题加$i$条边还是之前的问题加起来恰好$i$条边。后面看了题解才知道每个问题都是独立的,每次考虑前$i$个问题就可以了,对于第$i$个问题,可以重新构图,添加$i$条边来满足前$i$个条件。

  对于每个询问,要满足$x_i$和$y_i$连通,因此可以用并查集来维护。因此对于前$i$个问题,在添加完$i$条边后就会形成若干个连通块,假设有$m$个连通块,第$i$个连通块的大小为$\text{cnt}_i$。由于每个连通块相互独立,因此在考虑度数的时候分别看每个连通的最大度数。对于第$i$个连通块,我们可以构造一个菊花图,使得某个点的最大度数为$\text{cnt}_i - 1$。

  对于前$i$个询问,每个询问最多添加一条边就可以满足需求,因此添加$i$条边是一定可以满足前$i$个需求,有解。但实际上我们不一定要用$i$条边。比如如果$x_i$与$y_i$本身就已经连通了,如果我们再对$x_i$与$y_i$连一条边,实际上就是在该连通块内连一条边,并不能增加最大度数(某个连通块的最大度数都是$\text{cnt}_i - 1$,即连通块内点的个数减$1$)。因此对于多出来的边,我们可以用来连通某两个连通块,这样两个连通块就合并成了一个,新的连通块的某个点的最大度数就是$\text{cnt}_i + \text{cnt}_j - 1$,度数就变大了。

  因此对于前$i$个询问,看一下有多少条多余的边,假设为$s$,那么我们可以用这$s$条边来合并$s + 1$个连通块。为了使得得到的度数最大,可以按照连通块从大到小的顺序来合并。

  AC代码如下,时间复杂度为$O(n^2 \log {n})$:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int N = 1010;
 5 
 6 int fa[N], cnt[N];
 7 
 8 int find(int x) {
 9     return fa[x] == x ? fa[x] : find(fa[x]);
10 }
11 
12 int main() {
13     int n, m;
14     scanf("%d %d", &n, &m);
15     for (int i = 1; i <= n; i++) {
16         fa[i] = i;
17         cnt[i] = 1;
18     }
19     int s = 0;
20     vector<int> tmp;
21     for (int i = 1; i <= m; i++) {
22         int x, y;
23         scanf("%d %d", &x, &y);
24         x = find(x), y = find(y);
25         if (x != y) {
26             cnt[x] += cnt[y];
27             fa[y] = x;
28         }
29         else {  // x和y已经在同一个连通块,不需要再连边了
30             s++;
31         }
32         tmp.clear();
33         for (int i = 1; i <= n; i++) {
34             if (fa[i] == i) tmp.push_back(cnt[i]);
35         }
36         sort(tmp.begin(), tmp.end(), greater<int>());
37         int ret = 0;
38         for (int i = 0; i < tmp.size() && i < s + 1; i++) { // 选出最大的s+1个连通块进行合并
39             ret += tmp[i];
40         }
41         printf("%d\n", ret - 1);    // 最大度数就是构造菊花图,连通块的大小减1
42     }
43     
44     return 0;
45 }

 

日记

  这刚好是我的第$300$篇博客,也是我来博客园写博客的第$2$年,回想起当时什么都不会的我,再到现在已经掌握了大部分算法,还蛮多感慨的。我很怀念写博客的这段时间,因为我还蛮喜欢分享一些知识的见解和个人的想法,不过比较糟糕的是并没有很多人访问我的博客,感觉帮助到的人会比较少。不过这也或许说明了我的文字表达能力并不那么的优秀,博文的质量也没那么高,因此还有很多需要学习的地方。

  在这两年我学到了很多的数学和算法知识,也更加坚定了对数学和算法的喜爱。不过最近我的状态还蛮糟糕的,一方面不知道有没有机会保研,即使我已经尽我最大的努力,但还是一个概率的问题。另一方面是我找不到适合我的专业。虽说我是计算机专业,但实际上我更想读数学的专业。所以我找了$\text{tcs}$这个方向的专业,但不幸的是国内在这方面的资源十分匮乏,基本都集中在了国内最顶尖的高校,很明显我这种普通人是不可能达到这种高度的。所以我现在的情况还挺矛盾的。未来会怎么样真的很模糊,有很多不确定的因素,这也是我现在总是担心的地方。

  但不管怎么样,只要我对数学和算法的热情不减,就一定会继续写博客与网友分享我的知识和见解。

  最后放张《魔法少女小圆》的图吧,我很喜欢的一部动漫。话说我写了这么多的博客都没放过二次元的图片。

 

参考资料

  AcWing 4866. 最大数量(AcWing杯 - 周赛):https://www.acwing.com/video/4638/

标签:度数,连通,最大,int,text,leq,条边,数量
From: https://www.cnblogs.com/onlyblues/p/17167267.html

相关文章

  • LeetCode算法训练-贪心算法 455.分发饼干 376. 摆动序列 53. 最大子序和
    欢迎关注个人公众号:爱喝可可牛奶LeetCode算法训练-贪心算法455.分发饼干376.摆动序列53.最大子序和前置知识贪心算法核心是找局部最优解,通过局部最优推导出全局最......
  • 算法刷题 Day 60 | ● 84.柱状图中最大的矩形
    84.柱状图中最大的矩形有了之前单调栈的铺垫,这道题目就不难了。https://programmercarl.com/0084.%E6%9F%B1%E7%8A%B6%E5%9B%BE%E4%B8%AD%E6%9C%80%E5%A4%A7%E7%9A%84%......
  • LeetCode 84. 柱状图中最大的矩形()
    原题解题目约束题解方法一classSolution{public:intlargestRectangleArea(vector<int>&heights){intn=heights.size();vec......
  • 算法刷题-求最大连续bit数-JAVA
    0x00引言为获取一个良好的算法思维,以及不再成为一个脚本小子,争取每天一道算法题,培养自己的逻辑思维,温顾各类型语言语法知识。题解只写自己理解的解法,其他解法不再增加。......
  • 礼物的最大价值
    在一个m\timesnm×n的棋盘的每一格都放有一个礼物,每个礼物都有一定的价值(价值大于0)。你可以从棋盘的左上角开始拿格子里的礼物,并每次向右或者向下移动一格、直到到达棋盘......
  • 【LeetCode二叉树#11】最大二叉树(构造二叉树)
    最大二叉树力扣题目地址(opensnewwindow)给定一个不含重复元素的整数数组。一个以此数组构建的最大二叉树定义如下:二叉树的根是数组中的最大元素。左子树是通过数组......
  • 179. 最大数 (Medium)
    问题描述179.最大数(Medium)给定一组非负整数nums,重新排列每个数的顺序(每个数不可拆分)使之组成一个最大的整数。注意:输出结果可能非常大,所以你需要返回一个字符串而......
  • 打印从1到最大的n位数
    描述输入数字 n,按顺序打印出从1到最大的n位十进制数。比如输入3,则打印出1、2、3一直到最大的3位数999。1.用返回一个整数列表来代替打印2.n为正整数,0<......
  • 1792. 最大平均通过率 (Medium)
    问题描述1792.最大平均通过率(Medium)一所学校里有一些班级,每个班级里有一些学生,现在每个班都会进行一场期末考试。给你一个二维数组classes,其中classes[i]=[pass......
  • 1139. 最大的以 1 为边界的正方形 (Medium)
    问题描述1139.最大的以1为边界的正方形(Medium)给你一个由若干0和1组成的二维网格grid,请你找出边界全部由1组成的最大正方形子网格,并返回该子网格中的元素......