描述: 我们把序列排成不增序,即d1>=d2>=...>=dn,则d可简单图化当且仅当d'=(d2-1, d3-1, ... d(d1+1)-1, d(d1+2), d(d1+3), ... dn)可简单图化。这个定理写起来麻烦,实际上就是说,我们把d排序以后,找出度最大的点(设度为d1),把它和度次大的d1个点之间连边,然后这个点就可以不管了,一直继续这个过程,直到建出完整的图,或出现负度等明显不合理的情况。
举例:序列S:7,7,4,3,3,3,2,1 删除序列S的首项 7 ,对其后的7项每项减1,得到:6,3,2,2,2,1,0,继续删除序列的首项6,对其后的6项每项减1,得到:2,1,1,1,0,-1,到这一步出现了负数,因此该序列是不可图的。
其实仔细想想,就是贪心的构建一个图,一条边对应2个点产生两个度数,每次拿掉一个度数最大的点删掉与之相连的边(有点拓扑排序的意思),与之相连的点度数自然-1;
因为要尽可能连成图,当然是让度数大的点度数减少1,否则度数小的点减没了,就不能构成图了;
#include<cstdlib>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<set>
#include<cstring>
#include <algorithm>
#define inf 0x7fffffff
#define N 10000
#define MIN 1e-11
#define M 10000
#define LL long long
using namespace std;
int n,k,h;
int a[N];
int cmp(const void *a,const void *b)
{
return *(int*)b-*(int*)a;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("ex.in","r",stdin);
#endif
// scanf("%d%*c%*c",&t);
// int x=0;
while(scanf("%d",&n)&&n)
{
int num=0;
for(int i=0; i<n; ++i)
{
scanf("%d",&a[i]);
if(a[i])
num++;
}
int maxv,sub,ok=1;
int cnt=0;
while(num)
{
qsort(a,n,sizeof(a[0]),cmp);
num--;
if(a[0]>num)
{
ok=0;
break;
}
int cnt=0;
for(int i=1;a[i]&&i<n&&cnt!=a[0];i++)
{
a[i]--;
if(!a[i])
num--;
cnt++;
}
a[0]=0;
}
printf("%s\n",ok?"Possible":"Not possible");
}
return 0;
}