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;
}
View Code

 

posted @ 2019-03-14 08:27  Jessiejzy  阅读(417)  评论(0编辑  收藏  举报