题解 构图
发现可以 \(O(n^2)\)
那么枚举有 \(x\) 个点度数为 \(k\)
那么剩下的点度数和为 \(\max(kx, (k+1)(n-x))\)
若 \(\sum\deg-kx\) 不为偶数要补到偶数
将这些度数平均分配到 \(n-x\) 个点上是最优的
对这 \(x\) 个数模拟匹配过程
为了保证平均分配每次取 \(n-x\) 个数中当前剩余度数最大的
最后若这 \(n-x\) 个数中还有度数不为 0 的就两两配对即可
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 2000010
#define fir first
#define sec second
#define pb push_back
#define ll long long
//#define int long long
char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
int ans=0, f=1; char c=getchar();
while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
return ans*f;
}
int n, k;
int top;
pair<int, int> sta[N];
namespace task1{
void solve() {
printf("%d\n", k*(n-k));
for (int i=1; i<=k; ++i)
for (int j=k+1; j<=n; ++j)
printf("%d %d\n", i, j);
}
}
namespace task2{
void solve() {
int base=5;
for (int i=1; i+base-1<=n; i+=base) {
for (int j=i+2; j<=i+base-1; ++j) {
sta[++top]={i, j};
sta[++top]={i+1, j};
}
}
for (int i=1; i<=n%base; ++i) {
sta[++top]={1, n-i+1};
sta[++top]={2, n-i+1};
}
printf("%d\n", top);
for (int i=1; i<=top; ++i) printf("%d %d\n", sta[i].fir, sta[i].sec);
}
}
namespace task3{
void solve() {
int base=k<<1|1;
for (int i=1; i+base-1<=n; i+=base) {
for (int j=i+k; j<=i+base-1; ++j) {
for (int t=i; t<i+k; ++t)
sta[++top]={t, j};
}
}
for (int i=1; i<=n%base; ++i) {
for (int j=1; j<=k; ++j)
sta[++top]={j, n-i+1};
}
printf("%d\n", top);
for (int i=1; i<=top; ++i) printf("%d %d\n", sta[i].fir, sta[i].sec);
}
}
namespace force{
int deg[20], tot, ans=INF, rec;
pair<int, int> e[N];
void solve() {
for (int i=1; i<=n; ++i)
for (int j=i+1; j<=n; ++j)
e[tot++]={i, j};
int lim=1<<tot;
for (int s=0,cnt; s<lim; ++s) {
memset(deg, 0, sizeof(deg));
for (int i=0; i<tot; ++i) if (s&(1<<i)) {
++deg[e[i].fir]; ++deg[e[i].sec];
}
for (int i=1; i<=n; ++i) if (deg[i]<k) goto jump;
for (int i=0; i<tot; ++i) if (s&(1<<i)) {
if (deg[e[i].fir]==k && deg[e[i].sec]==k) goto jump;
}
cnt=__builtin_popcount(s);
if (cnt<ans) ans=cnt, rec=s;
jump: ;
}
cout<<ans<<endl;
for (int i=0; i<tot; ++i) if (rec&(1<<i)) printf("%d %d\n", e[i].fir, e[i].sec);
}
}
namespace task{
int maxn=INF, maxi;
map<pair<int, int>, bool> mp;
vector<pair<int, int>> tem;
priority_queue<pair<int, int>> q;
void solve(int x) {
int lim=max(k*x, (k+1)*(n-x));
if ((lim-k*x)&1) ++lim;
int cnt=lim-(lim/(n-x)*(n-x));
for (int i=1; i<=n-x; ++i) q.push({lim/(n-x)+((cnt--)>0), n-i+1});
for (int i=1; i<=x; ++i) {
pair<int, int> t;
for (int j=1; j<=k; ++j) {
t=q.top(); q.pop();
sta[++top]={i, t.sec};
if (t.fir>1) tem.pb({t.fir-1, t.sec});
}
while (tem.size()) q.push(tem.back()), tem.pop_back();
}
// while (q.size()) cout<<"("<<q.top().fir<<','<<q.top().sec<<") ", q.pop(); cout<<endl;
while (q.size()) {
pair<int, int> u=q.top(); q.pop();
// cout<<"u: "<<u.fir<<' '<<u.sec<<endl;
while (u.fir) {
pair<int, int> v=q.top(); q.pop();
sta[++top]={u.sec, v.sec};
--u.fir;
if (v.fir>1) tem.pb({v.fir-1, v.sec});
// cout<<"uv: "<<u.sec<<' '<<v.sec<<endl;
}
while (tem.size()) q.push(tem.back()), tem.pop_back();
}
printf("%d\n", top);
for (int i=1; i<=top; ++i) printf("%d %d\n", sta[i].fir, sta[i].sec);
}
int query(int x) {
int lim=max(k*x, (k+1)*(n-x));
if ((lim-k*x)&1) ++lim;
int ans=k*x + (lim-k*x)/2;
return ans;
}
void solve() {
for (int i=1; i<=n-k; ++i) {
int t=query(i);
if (t<maxn) maxn=t, maxi=i;
}
// cout<<"maxi: "<<maxi<<endl;
solve(maxi);
}
}
signed main()
{
freopen("graph.in", "r", stdin);
freopen("graph.out", "w", stdout);
n=read(); k=read();
// task1::solve();
// task2::solve();
// if (n<=7) force::solve();
// else task3::solve();
task::solve();
return 0;
}