CF976D. Degree Set
题目大意:
给你一个长度为 $n$ 的正整数序列 $d\_1, d\_2, ......, d\_n$ ( $d\_1 < d\_2 < ...... < d\_n$ )。要求你构造一个满足以下条件的无向图:
1. 有恰好 $d_n + 1$ 个点;
2. 没有自环;
3. 没有重边;
4. 总边数不超过 $10^6$ ;
5. 它的度数集合等于 $d$ 。
点从 $1$ 标号至 $d_n + 1$ 。
图的度数序列是一个长度与图的点数相同的数组 $a$ ,其中 $a_i$ 是第 $i$ 个顶点的度数(与其相邻的顶点数)。
图的度数集合是度数序列排序后去重的结果。
保证有解,要求输出符合条件的图。
思路:
对于对于前 $d[1]$ 个点向所有点连接一条边于是现在当前局面里有 $d[1]$ 个点为度数 $d[n]$ ,其余点度数为 $d[1]$ ,所以我们对于度数为 $d[n]$ 的 $d[1]$ 个点不再进行操作,对于度数为 $d[n]$ 的 $d[n]-d[n-1]$ 个点也不再操作。那么问题就转化成子问题,构造 $(d[2]-d[1],d[3]-d[1],......,d[n-1]-d[1])$ 的子问题。
以下代码:
#include<bits/stdc++.h> #define il inline #define _(d) while(d(isdigit(ch=getchar()))) using namespace std; const int N=1e6+5; int n,tot,cnt,d[N]; struct node{ int x,y; }t[N]; il int read(){ int x,f=1;char ch; _(!)ch=='-'?f=-1:f;x=ch^48; _()x=(x<<1)+(x<<3)+(ch^48); return f*x; } il void ins(int x,int y){ t[++tot]=(node){x,y}; } int main() { n=read(); for(int i=1;i<=n;i++)d[i]=read(); int L=1,R=d[n]+1; for(int i=1,j=n;i<=(n>>1);i++,j--){ for(int k=1;k<=d[i];k++)for(int l=L;l<R-k+1;l++) t[++tot]=(node){R-k+1,l}; L+=d[j]-d[j-1];R-=d[i]; for(int k=i+1;k<j;k++)d[k]-=d[i]; } if(n&1){ for(int i=L;i<=R;i++){ for(int j=L;j<i;j++)t[++tot]=(node){i,j}; } } printf("%d\n",tot); for(int i=1;i<=tot;i++)printf("%d %d\n",t[i].x,t[i].y); return 0; }