这道题费了我好大力气,理理思路先。
开始只想到了一些图的基本性质:
1、联通图度数和是边数的二倍。
2、度数为奇数的结点有偶数个。
3、对于简单图,点的度数不能大于点的总个数。
不过凭这些性质根本不能有效的判断啊,比如输入是 4 3 3 1 1 ,就不可能是简单图,但我已经没有了别的判断依据。
而且,题目的意思我也没完全理解,题目说的简单图,不一定要连通。
想到可能要用贪心的策略一个一个点的去判断,但也没想出什么具体的策略,更别提证明了。。。
只有上网搜了,才知道有个Havel-Hakimi定理 见链接http://blog.csdn.net/shuangde800/article/details/7857246 。这个定理在写的时候也要注意,i+s[i]不能大于N-1,
不过我还是觉得这题没完全弄懂,因为我觉得不靠这个定理就用贪心的思想就可以找到方法的(或者说,这个定理本来就是运用的贪心策略)。但是不知道怎么严密的证明,只是隐约觉得,度数大的点优先与度数大的点配对更有可能构成简单图。。。。自己思路还不是很清晰啊。。。
另外,之前也遇到过了,sort 里的cmp函数只需判断小于关系就行了,而qsort需要三中关系都有返回值。
#include<cstdio>
#include<cstring>
#include<algorithm>
#define MAX 10100
using namespace std;
int s[MAX];
bool cmp(int a,int b)
{
if(b-a<0)
return 1;
return 0;
}
int main()
{
int n,i,j,flag,js,all,big;
long long sum;
while(scanf("%d",&n)&&n)
{
flag=1,js=0,sum=0,all=0,big=0;
for(i=0;i<n;i++)
{
scanf("%d",&s[i]);
if(s[i])
all++;
if(s[i]%2==1)
js++;
if(s[i]>big)
big=s[i];
sum=(sum+s[i]);
}
if(sum%2==1||js%2==1||big>=all)
flag=0;
if(sum==0)
{
printf("Possible\n");
continue;
}
if(flag==1)
{
for(i=0;i<n-1;i++)
{
if(i+s[i]>n-1)
{
flag=0;
goto next;
}
sort(s+i,s+n,cmp);
for(j=i+1;j<=i+s[i];j++)
{
s[j]--;
if(s[j]<0)
{
flag=0;
goto next;
}
}
}
}
next:
if(flag==0||s[n-1]!=0)
printf("Not possible\n");
else
printf("Possible\n");
}
return 0;
}