2017年3月18日 | ljfcnyali
题目大意:
给出一个图的每个点的度的序列,求能否构成一个简单图;
Sample Input
2
6 4 4 3 3 2 2
4 2 1 1 1
Sample Output
yes
no
题目分析:使用Havel定理,可以轻易地AC。
Havel定理:
给定一个非负整数序列{dn};
若存在一个无向图使得图中各点的度与此序列一一对应;
则称此序列可图化。
若图为简单图,则称此序列可简单图化;
可图化的判定:
d1+d2+……dn=0(mod 2)。
关于具体图的构造,我们可以简单地把奇数度的点配对,剩下的全部搞成自环;
可简单图化的判定(Havel定理):
把序列排成不增序,即d1>=d2>=……>=dn;
则d可简单图化当且仅当d’={d2-1,d3-1,……d(d1+1)-1, d(d1+2),d(d1+3),……dn}可简单图化。
简单的说,把d排序后,找出度最大的点(设度为d1);
把它与度次大的d1个点之间连边,然后这个点就可以不管了;
一直继续这个过程,直到建出完整的图,或出现负度等明显不合理的情况。
1 把度排序,从大到小;
2 总的度mod 2=0;
3 最大度<=n-1;
AC代码实在是太水了:
/*************************************************************************
> File Name: HDU2454.cpp
> Author: ljf-cnyali
> Mail: ljfcnyali@gmail.com
> Created Time: 2017/3/18 9:10:32
************************************************************************/
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<map>
#include<set>
#include<vector>
#include<queue>
using namespace std;
#define REP(i, a, b) for(int i = (a), _end_ = (b);i <= _end_; ++ i)
#define mem(a) memset((a), 0, sizeof(a))
#define str(a) strlen(a)
const int maxn = 1010;
int n, m;
int a[maxn];
int cmp(int x, int y) {
return x > y;
}
int main() {
#ifndef ONLINE_JUDGE
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
#endif
int T;
scanf("%d", &T);
while(T --) {
scanf("%d", &n);
int sum = 0;
REP(i, 1, n) {
scanf("%d", &a[i]);
sum += a[i];
}
if(sum % 2 != 0) {
printf("no\n");
continue;
}
bool flag = false;
REP(i, 1, n) {
sort(a + 1, a + n + 1, cmp);
if(a[1] == 0) {
flag = true;
break;
}
int k = 0;
REP(j, 1, a[1]) {
-- a[j + 1];
if(a[j + 1] < 0) {
k = 1;
break;
}
}
a[1] = 0;
if(k == 1)
break;
}
if(flag == false)
printf("no\n");
else
printf("yes\n");
}
return 0;
}