Problem F. 自建一始

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

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值