题目
题目链接:http://poj.org/problem?id=1659
题目来源:《图论算法理论、实现及应用》例题
简要题意: N 个青蛙每个青蛙有
xi 个邻居,问可不可能,可能给出一个邻接矩阵。数据范围: 0⩽T⩽20;2<N<10;0⩽xi⩽N
题解
可图性的判定有一个定理,使用了贪心的思想:
- 将剩余的度数从大到小排序,设为 s1,s2⋯sk
- 将 s1 删去,将 s1 后面 s1 个度数每个减去 1 ,如果没有这么多或产生负数就不可图。
- 如果没有节点了则是可图的,不然返回1.步骤
定理其实直接描述了做的过程,高度数的点和高度数的点连比较有利。
实现
跟着做就是了,每次取都需要排序,因为减了之后可以有序被破坏。
最终的复杂度为
Θ(N2logN) 。
代码
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <stack>
#include <queue>
#include <string>
#include <vector>
#include <set>
#include <map>
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define sz(x) ((int)(x).size())
#define fi first
#define se second
using namespace std;
typedef long long LL;
typedef vector<int> VI;
typedef pair<int,int> PII;
LL powmod(LL a,LL b, LL MOD) {LL res=1;a%=MOD;for(;b;b>>=1){if(b&1)res=res*a%MOD;a=a*a%MOD;}return res;}
// head
const int N = 15;
bool e[N][N];
PII a[N];
bool isGraghpic(int n) {
int u, v;
for (int i = 0; i < n; i++) {
sort(a+i, a+n, greater<PII>());
for (int j = i+1; j < n && a[i].fi; j++) {
a[i].fi--, a[j].fi--;
u = a[i].se, v = a[j].se;
e[u][v] = e[v][u] = true;
}
if (a[i].fi) return false;
}
return true;
}
void p(int n, bool flag) {
puts(flag ? "YES" : "NO");
if (!flag) return;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
printf("%d%c", e[i][j], j == n-1 ? '\n' : ' ');
}
}
}
int main()
{
int t, n;
scanf("%d", &t);
while (t--) {
scanf("%d", &n);
for (int i = 0; i < n; i++) {
scanf("%d", &a[i].fi);
a[i].se = i;
}
p(n, isGraghpic(n));
if (t) {
puts("");
}
memset(e, 0, sizeof e);
}
return 0;
}