/*
一开始用了带剪枝的搜索,不知道为什么一直WA
后来改成havel贪心定理才AC,有兴趣的拿去研究下下面这个搜索为什么过不了
#include <iostream>
#define MAX_S 600
#define MAX_N 9
using namespace std;
int states[MAX_N + 1][MAX_S + 1];
int curStates[MAX_N + 1];
int expv[MAX_N + 1];
int num[MAX_N + 1];
int n;
void getExp()
{
expv[0] = 1;
for(int i = 1; i <= MAX_N; i++)
expv[i] = expv[i - 1] * 2;
}
void getAllState(int pos, int num, int state)
{
if(pos == n)
{
states[num][0]++;
states[num][states[num][0]] = state;
return;
}
getAllState(pos + 1, num + 1, state | expv[pos]);
getAllState(pos + 1, num, state);
}
bool can;
void solve(int pos, int curStates[])
{
if(pos == n)
{
can = true;
return;
}
int p, k;
for(p = 1; p <= states[num[pos]][0] && !can; p++)
{
int curS = states[num[pos]][p];
if(curS & expv[pos]) continue;
for(k = 0; k < pos; k++)
{
int can1 = curStates[k] & expv[pos];
int can2 = curS & expv[k];
//剪枝
if((can1 != 0 && can2 == 0) || (can1 == 0 && can2 != 0))
break;
}
if(k < pos) continue;
curStates[pos] = curS;
solve(pos + 1, curStates);
}
}
int main()
{
int caseN, i, j;
getExp();
scanf("%d", &caseN);
while(caseN--)
{
scanf("%d", &n);
memset(states, 0, sizeof(states));
memset(curStates, 0, sizeof(curStates));
getAllState(0, 0, 0);
for(i = 0; i < n; i++) scanf("%d", &num[i]);
can = false;
solve(0, curStates);
if(can)
{
printf("YES/n");
for(i = 0; i < n; i++)
{
for(j = 0; j < n; j++)
{
if(j != 0) printf(" ");
if(curStates[i] & expv[j]) printf("1");
else printf("0");
}
printf("/n");
}
}
else printf("NO/n");
printf("/n");
}
return 0;
}
*/
/*havel定理版本*/
#include <iostream>
#include <algorithm>
#define MAX_S 600
#define MAX_N 9
using namespace std;
int n;
struct node
{
int idseq, degree;
bool connect[MAX_N + 1];
}nodes[MAX_N + 1];
bool compare1(const node &n1, const node &n2)
{
return n1.degree >= n2.degree;
}
bool compare2(const node &n1, const node &n2)
{
return n1.idseq <= n2.idseq;
}
bool havel()
{
int i, j, deg, fid, tid;
for(i = 0; i < n; i++)
{
sort(&nodes[i], &nodes[i] + n - i, compare1);
deg = nodes[i].degree;
fid = nodes[i].idseq;
if(n - 1 - i < deg) return false;
for(j = i + 1; j <= i + deg; j++)
{
tid = nodes[j].idseq;
nodes[i].connect[tid] = true;
nodes[j].connect[fid] = true;
nodes[j].degree--;
if(nodes[j].degree < 0) return false;
}
}
return true;
}
int main()
{
int caseN, i, j;
scanf("%d", &caseN);
while(caseN--)
{
scanf("%d", &n);
for(i = 0; i < n; i++)
{
scanf("%d", &nodes[i].degree);
nodes[i].idseq = i;
memset(nodes[i].connect, 0, sizeof(nodes[i].connect));
}
bool can = havel();
sort(nodes, nodes + n, compare2);
if(can)
{
printf("YES/n");
for(i = 0; i < n; i++)
{
for(j = 0; j < n; j++)
{
if(j != 0) printf(" ");
if(nodes[i].connect[j]) printf("1");
else printf("0");
}
printf("/n");
}
}
else printf("NO/n");
printf("/n");
}
return 0;
}
/*补充havel定理相关内容(摘自http://203.208.39.132/search?q=cache:FizGQJ-6NaoJ:hi.baidu.com/roba/blog/item/0732d01645a9ec1b972b4380.html+harvel+%E5%AE%9A%E7%90%86&cd=1&hl=zh-CN&ct=clnk&gl=cn&st_usg=ALhdy2_AdwSZ0NavagiEda9fBTYrC38mXg):
给定一个非负整数序列{d1,d2,...dn},若存在一个无向图使得图中各点的度与此序列一一对应,则称此序列可图化。进一步,若图为简单图,则称此序列可简单图化。
可图化的判定比较简单:d1+d2+...dn=0(mod2)。关于具体图的构造,我们可以简单地把奇数度的点配对,剩下的全部搞成自环。
可简单图化的判定,有一个Havel定理,是说: 我们把序列排成不增序,即d1>=d2>=...>=dn,则d可简单图化当且仅当d'=(d2-1, d3-1, ... d(d1+1)-1, d(d1+2), d(d1+3), ... dn)可简单图化。实际上就是说,我们把d排序以后,找出度最大的点(设度为d1),把它和度次大的d1个点之间连边,然后这个点就可以不管了,一直继续这个过程,直到建出完整的图,或出现负度等明显不合理的情况。
*/