POJ-1659 Frogs' Neighborhood

34 篇文章 0 订阅
Frogs' Neighborhood
Time Limit: 5000MS Memory Limit: 10M
  Special Judge

Description

未名湖附近共有N个大小湖泊L1, L2, ..., Ln(其中包括未名湖),每个湖泊Li里住着一只青蛙Fi(1 ≤iN)。如果湖泊LiLj之间有水路相连,则青蛙FiFj互称为邻居。现在已知每只青蛙的邻居数目x1,x2, ...,xn,请你给出每两个湖泊之间的相连关系。

Input

第一行是测试数据的组数T(0 ≤ T ≤ 20)。每组数据包括两行,第一行是整数N(2 < N < 10),第二行是N个整数,x1,x2,...,xn(0 ≤xiN)。

Output

对输入的每组测试数据,如果不存在可能的相连关系,输出"NO"。否则输出"YES",并用N×N的矩阵表示湖泊间的相邻关系,即如果湖泊i与湖泊j之间有水路相连,则第i行的第j个数字为1,否则为0。每两个数字之间输出一个空格。如果存在多种可能,只需给出一种符合条件的情形。相邻两组测试数据之间输出一个空行。

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 

————————————————————POJ的分割线————————————————————

前言:蓝书到手,开始学图论基础知识了。

思路:例1.2。根据度序列建图。用到Havel-Hakimi定理。度序列s可图当且仅当序列

s1: d[2]-1, d[3]-1, ..., d[d[1]+1]-1, d[d[1]+2]-1, ..., d[n]

可图。

按照这个方法,存储每个顶点的度数和下标,然后每次非增排序,删去首项d[1]后,将它的度数和它后面d[1]项抵消,直到所有项变成0或者出现负数(不可图)。

PS:注意是无向图,所以G[i][j] = G[j][i] = 1

代码如下:

/*
ID: j.sure.1
PROG: 
LANG: C++
*/
/****************************************/
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <stack>
#include <queue>
#include <vector>
#include <map>
#include <string>
#include <iostream>
using namespace std;
/****************************************/
bool G[15][15];
struct Node
{
	int id;
	int deg;
}vg[15];

bool cmp(Node a, Node b)
{
	return a.deg > b.deg;
}

int main()
{
	//freopen("1659.in", "r", stdin);
	//freopen("1659.out", "w", stdout);
	int T;
	scanf("%d", &T);
	while(T--) {
		int n;
		bool ok = true;
		scanf("%d", &n);
		for(int i = 0; i < n; i++) {
			scanf("%d", &vg[i].deg);
			vg[i].id = i;
		}
		memset(G, 0, sizeof(G));
		sort(vg, vg+n, cmp);
		while(vg[0].deg) {
			for(int i = 1; i <= vg[0].deg; i++) {
				vg[i].deg--;
				if(vg[i].deg < 0) {
					ok = false;
					break;
				}
				G[vg[i].id][vg[0].id] = G[vg[0].id][vg[i].id] = true;
			}
			vg[0].deg = 0;
			sort(vg, vg+n, cmp);
		}
		if(ok) {
			puts("YES");
			for(int i = 0; i < n; i++) {
				printf("%d", G[i][0]);
				for(int j = 1; j < n; j++) {
					printf(" %d", G[i][j]);
				}
				printf("\n");
			}
		}
		else {
			puts("NO");
		}
		if(T)
			puts("");
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值