【贪心】P7403 [BalticOI 2002 Day1] Tennis Club
目前题解区还没有证明,我交个证明。
形式化题意
给定每个点的度数
First. 无解
首先,根据握手定理,每个无向图的度数之和为边数的两倍,所以如果度数之和为奇数,那么肯定无解。
但是发现,这种情况之外还有别的无解情况(本题有
而这种情况,就需要给出一个保证正确的构造方案,如果无法构造那么无解。
Second. 构造
这里介绍一个定理:
Havel-Hakimi定理
一个不降序度数序列
若其可以简单图化,当且仅当 可以简单图化。
-
证明:
若其可以简单图化,那么 可以简单图化。两种情况:
- 图
中存在边 ,显然,此时删去这些边该图仍然为简单图且满足度数序列 ,所以 可简单图化。 - 图
中存在点对 满足 且仅存在边 而不存在边 且 ,那么此时由于 那么一定存在一个点 满足存在 但不存在 ,将 修改为 , 修改为 ,该图度数序列不变且仍然为简单图,此时,情况又变为情况 。
- 图
-
证明:
可以简单图化,那么 可以简单图化。
构造很简单, 与 连边,该图仍为简单图,且度数序列变为 。
显然,度数序列
如果不能进行如上操作(即
注意,定理中的
Code
#include <bits/stdc++.h>
using namespace std;
const int N = 1e3 + 10;
int n;
pair<int, int> g[N];
vector<int> ans[N];
signed main() {
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin >> n;
int d = 0;
for (int i = 1; i <= n; i ++) {
cin >> g[i].first;
g[i].second = i, d += g[i].first;
}
if (d & 1) { // 握手定理
cout << "NO SOLUTION\n";
return 0;
}
for (int t = 1; t <= n; t ++) {
sort(g + 1, g + 1 + n); // 排序
int j = n - 1;
while (g[n].first) { // 从次大值开始减
g[j].first --, g[n].first --;
if(g[j].first < 0) { //无法加边,无解
cout << "NO SOLUTION\n";
return 0;
}
ans[g[j].second].push_back(g[n].second);
ans[g[n].second].push_back(g[j].second);
j --;
}
}
cout << "SOLUTION\n";
for (int i = 1; i <= n; i ++) {
for (auto u : ans[i]) cout << u << ' ';
cout << endl;
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)