POJ 1659 Frogs' Neighborhood

题目大意:中文

题目链接

注释代码:

/*                                 
 * Problem ID : POJ 1659 Frogs' Neighborhood
 * Author     : Lirx.t.Una                                 
 * Language   : C++                     
 * Run Time   : 0 ms                                 
 * Run Memory : 132 KB                                 
*/ 

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>

//最大点数
#define	MAXN	10

using namespace std;

//思路:本题是根据无向图中点的度数求原图
//实际为拓扑排序的逆过程

struct	Node {//表示每个点

	char	id;//记录每个点的序号
	char	deg;//点的度数

	bool//对点按照从大到小排列
	operator<(const Node &oth)
	const {
	
		return deg > oth.deg;
	}
};

Node	node[MAXN];//点
bool	g[MAXN][MAXN];//原图

bool
toplink(int n) {//拓扑连接,为拓扑排序的逆过程

	int		i, j;//计数变量
	int		deg;//临时度数变量

	for ( i = 0; i < n; i++ ) {
	
		//每跟新一次度数就重排一次,重排的起始点为上次摘掉的点的后面一个位置
		//前面的点由于度数都分配完了,因此就没有考虑的必要了
		sort(node + i, node + n);

		//这就是按照度数从大到小排的原因了,如果当前点的度数比剩余点数都多
		//这就说明度数无法分配完,这种情况必定是不允许的,因为两点之间不能有超过1条边
		if ( ( deg = node[i].deg ) > n - i - 1 ) return false;
		if ( !deg ) return true;//表示入度已经全部分配完,因为是按照入度从大到小排列的
		//因此当前点度为0就意味着后面的点度也必定为0,也就代表多有点的度都为0了
		//就表示度数已经分配完了

		for ( j = i + 1; j <= i + deg; j++ ) {//由于是从头到尾遍历跟新度数的,因此按照
			//度数从大到小排列可以是入度分配地更加快从而加速算法,当然从小到大排算法也是
			//一样的,就是速度不如从大到小来的快
		
			if ( !node[j].deg ) return false;//但是后面的点的度数不够此次分配也将导致失败

			node[j].deg--;//跟新并连边
			g[ node[i].id ][ node[j].id ] = true;
			g[ node[j].id ][ node[i].id ] = true;
		}
		node[i].deg = 0;//当前点度数分配完就置0
	}

	return true;
}

int
main() {

	int		t;//测例数
	int		n;//点数

	int		i, j;//计数变量

	scanf("%d", &t);
	while ( t-- ) {
	
		memset(g, false, sizeof(g));

		scanf("%d", &n);
		for ( i = 0; i < n; i++ ) {
			
			node[i].id = i;
			scanf("%d", &node[i].deg);
		}

		if ( !toplink(n) )
			puts("NO");
		else {

			puts("YES");
			for ( i = 0; i < n; putchar('\n'), i++ )
				for ( j = 0; j < n; j++ )
					printf("%d ", g[i][j]);
		}
		putchar('\n');
	}

	return 0;
}
无注释代码:

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>

#define	MAXN	10

using namespace std;

struct	Node {

	char	id;
	char	deg;

	bool
	operator<(const Node &oth)
	const {
	
		return deg > oth.deg;
	}
};

Node	node[MAXN];
bool	g[MAXN][MAXN];

bool
toplink(int n) {

	int		i, j;
	int		deg;

	for ( i = 0; i < n; i++ ) {
	
		sort(node + i, node + n);
		if ( ( deg = node[i].deg ) > n - i - 1 ) return false;
		if ( !deg ) return true;

		for ( j = i + 1; j <= i + deg; j++ ) {
		
			if ( !node[j].deg ) return false;

			node[j].deg--;
			g[ node[i].id ][ node[j].id ] = true;
			g[ node[j].id ][ node[i].id ] = true;
		}
		node[i].deg = 0;
	}

	return true;
}

int
main() {

	int		t;
	int		n;

	int		i, j;

	scanf("%d", &t);
	while ( t-- ) {
	
		memset(g, false, sizeof(g));

		scanf("%d", &n);
		for ( i = 0; i < n; i++ ) {
			
			node[i].id = i;
			scanf("%d", &node[i].deg);
		}

		if ( !toplink(n) )
			puts("NO");
		else {

			puts("YES");
			for ( i = 0; i < n; putchar('\n'), i++ )
				for ( j = 0; j < n; j++ )
					printf("%d ", g[i][j]);
		}
		putchar('\n');
	}

	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值