描述: 我们把序列排成不增序,即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; }