Problem F. 自建一始
Input file: standard input
Output file: standard output
Time limit: 2 seconds
Memory limit: 512 megabytes
Cuber QQ 接到任务要帮助自建一始村。
一始村可以认为是一个简单无向图 G(V, E),图中的顶点对应一个居民的住处,对于任意两个点 u, v,如
果 {u, v} ̸∈ E 并且 degu + degv ≥ k,则 Cuber QQ 可以修建这条道路,即将边 {u, v} 加入 E 中了,其中
degu 表示的时图中节点 u 的度数,即顶点 u 所连边的条数。
现在 Cuber QQ 想要找到最大的 k,使得在采取最优策略时可以将给定的图补全成一个完全图,让一始村
中的居民住处之间可以两两互相直接到达,完全图是指对于任意一对顶点 u ̸= v, {u, v} ∈ E。
Input
第一行两个整数 n, m(2 ≤ n ≤ 500, 0 ≤ m < n(n−1)
2
) ,代表给定图的顶点数以及初始时边数。
接下来 m 行,每行两个整数 u, v(1 ≤ u, v ≤ n, u ̸= v),表示 u, v 之间有一条无向边。保证给出的图是没
有重边,没有自环的简单图。
Output
输出一行一个整数,表示最大的 k,表示答案。
Page 12 of 21
2023 年(第十五届)四川省大学生程序设计大赛
都江堰, 成都
Example
standard input standard output
4 3
2 3
2 1
1 3
2
很遗憾当时没想出来没拿银
#include<bits/stdc++.h>
using namespace std;
const int N = 550;
int a[N], d[N],dd[N];
int n, m;
bool con[N][N], conn[N][N];
typedef pair<int, int>PII;
bool check(int x) {
queue<PII> q;
for (int i = 1; i <= n; i++)
dd[i] = d[i];
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
conn[i][j] = con[i][j];
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
{
if (conn[i][j])continue;
if (dd[i] + dd[j] >= x)
{
dd[i]++, dd[j]++;
conn[i][j] = conn[j][i] = 1;
q.push({ i,j });
}
}
while (q.size()) {
PII k = q.front();
q.pop();
int u = k.first, v = k.second;
for (int i = 1; i <= n; i++)
{
if (!conn[u][i] && dd[i] + dd[u] >= x)
{
dd[i]++, dd[u]++;
conn[i][u] = conn[u][i] = 1;
q.push({ u,i });
}
}
for (int i = 1; i <= n; i++) {
if (!conn[v][i] && dd[i] + dd[v] >= x)
{
dd[i]++, dd[v]++;
conn[i][v] = conn[v][i] = 1;
q.push({ v,i });
}
}
}
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
if (!conn[i][j])
return false;
return true;
}
int main()
{
cin >> n >> m;
for (int i = 0; i < m; i++)
{
int a, b;
cin >> a >> b;
d[a]++, d[b]++;
con[a][b] = con[b][a] = 1;
}
for (int i = 1; i <= n; i++)con[i][i] = 1;
int l = 0, r = 2 * n;
while (l<=r)
{
int mid = l + r >> 1;
if (check(mid)) {
l = mid + 1;
}
else {
r = mid - 1;
}
}
cout << r << endl;
}
ok…我宣布个事我是sb