题意:中文题,至少不用苦心的去读题了。给出了n个湖泊的n个青蛙,依次给出n个青蛙的邻居关系,判断这种关系能否成立 。若能够成立,写出代表两个湖泊关系的邻接矩阵。
矩阵写法多种 所以special judge.......
Sample Input
3 7 4 3 1 5 4 2 1 6 4 3 1 4 2 0 6 2 3 1 1 2 1
Sample Output
YES 0 1 0 1 1 0 1 1 0 0 1 1 0 0 0 0 0 1 0 0 0 1 1 1 0 1 1 0 1 1 0 1 0 1 0 0 0 0 1 1 0 0 1 0 0 0 0 0 0 NO YES 0 1 0 0 1 0 1 0 0 1 1 0 0 0 0 0 0 1 0 1 0 0 0 0 1 1 0 0 0 0 0 0 1 0 0 0
思路:学到一种新的方法:havel算法。
/*Havel算法的思想简单的说如下:
(1)对序列从大到小进行排序。
(2)设最大的度数为 t ,把最大的度数置0,然后把最大度数后(不包括自己)的 t 个度数分别减1(意思就是把度数最大的点与后几个点进行连接)
(3)如果序列中出现了负数,证明无法构成。如果序列全部变为0,证明能构成,跳出循环。前两点不出现,就跳回第一步!
*/
有了这个,判断能否构成图就轻松多了,邻接矩阵则在每次判断中进行构建。
代码:
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <vector>
#include <set>
#include <queue>
#include <stack>
#include <climits>//形如INT_MAX一类的
using namespace std;
#define MAX 1050
#define INF 0x7FFFFFFF
# define eps 1e-5
struct node
{
int index;
int neigh;
} lake[11];
bool cmp(node a,node b)
{
return a.neigh>b.neigh;
}
int map[11][11];
int main()
{
int t,i,n,j;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(i=1; i<=n; i++)
{
scanf("%d",&lake[i].neigh);//每个青蛙周围的青蛙
lake[i].index=i;//第n个青蛙
}
memset(map,0,sizeof(map));
for(i=1;;)
{
sort(lake+1,lake+n+1,cmp);//havel第一步
int index=0;
for(j=i+1; j<=lake[i].neigh+1; j++)
{
lake[j].neigh--;//havel第二步
if(lake[j].neigh<0)//havel第三步
{
i=n;//为下个if(i!=n)判断
index=n;//此处赋值只是为了退出循环
printf("NO\n");
break;
}
map[lake[i].index][lake[j].index]=1;//这两行邻接矩阵构建,说明相连
map[lake[j].index][lake[i].index]=1;
}
lake[i].neigh=0;//havel第二步
if(index==n)
break;
for(int k=1; k<=n; k++)//所有为零 构成图
{
if(lake[k].neigh==0)
{
index++;
}
}
if(index==n)
break;
}
if(i!=n)//对应上面
{
printf("YES\n");
for(i=1; i<=n; i++)//输出邻接矩阵
{
for(j=1; j<=n-1; j++)
{
printf("%d ",map[i][j]);
}
printf("%d\n",map[i][n]);
}
}
printf("\n");
}
return 0;
}