VEXOBEN
Vexoben
May 3, 2018
It takes 4 minutes to read this article.

题目链接:http://codeforces.com/problemset/problem/976/D

题意

升序给出一个大小为n的集合d,构造一张无向图,它所有点度数组成的集合恰好等于集合d

n<=1000,di<=1000

题解

考虑如果得到了一张图G,他的度数集合是{d[2]-d1,d[3]-d1,……,d[n-1]-d1},点数为(d[n-1]-d1+1)我们可以用如下的方式构造出集合d

1、构造一个点数为d1的完全图K,那么K中所有点的度数均为d1

2、K中所有点向G中是所有点连一条边,G的度数集合变成{d[2],d[3],……,d[n-1]},K中点的度数变成d[n-1];

3、将剩下尚未使用的(d[n]-d[n-1])个点向K中所有点连边,K中点度数变为d[n],其余点度数变为d1

那么当n>=2时用上面的方法递归,边界条件是:

a.若n=0,返回一个点;

b.若n=1,返回(d1+1)个点的完全图

#include<bits/stdc++.h>
using namespace std;

int n,tot;
vector<pair<int,int> > ans;
vector<int> d;

void Solve(vector<int> d) {
	if (d.size()==0) return (void) (++tot);
	if (d.size()==1) {
		int fir=tot+1;	tot+=d[0]+1;
		for (int i=fir;i<=tot;i++)
			for (int j=i+1;j<=tot;j++)
				ans.push_back(make_pair(i,j));
		return;
	}
	vector<int> dx; dx.clear();
	for (int i=1;i<d.size()-1;i++) dx.push_back(d[i]-d[0]);
	Solve(dx);
	int now=tot; tot+=d[0];
	for (int i=now+1;i<=tot;i++)
		for (int j=i+1;j<=tot;j++)
			ans.push_back(make_pair(i,j));
	for (int i=1;i<=now;i++)
		for (int j=now+1;j<=tot;j++)
			ans.push_back(make_pair(i,j));
	int K=tot; tot=d[d.size()-1]+1;
	for (int i=now+1;i<=K;i++)
		for (int j=K+1;j<=tot;j++)
			ans.push_back(make_pair(i,j));
}

int main() {
	scanf("%d",&n);
	for (int i=1;i<=n;i++) {
		int x; scanf("%d",&x);
		d.push_back(x);
	}
	Solve(d);
	printf("%d\n",ans.size());
	for (int i=0;i<ans.size();i++) 
		printf("%d %d\n",ans[i].first,ans[i].second);
	return 0;
}