题解 构图

传送门

发现可以 \(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;
}
posted @ 2022-04-04 16:23  Administrator-09  阅读(3)  评论(0编辑  收藏  举报