POJ:1659Frogs' Neighborhood

http://poj.org/problem?id=1659

此题是判断输入的数字序列数不是可图的,在这里我们采用Havel-Hakimi定理。Havel-Hakimi定理如下:

Havel-Hakimi 定理:

由非负整数组成的非递增序列sd1,d2 ,.....dn (n>=2 , d1>=1)

是可图的,当且仅当序列

s1:d2 -1 d3 - 1 ,......dd1+1 ,dd1+2,......d

是可图的。序列s1中有n-1个非负整数,s序列中d1后的前d1个度数(即d2~dd1+1)减1后构成s1中的前d1个数。

例如:序列s:7,7,4,3,3,3,2,1是否可图,删除序列s的首项7,对其后的7项每项减1,得到:6,3,2,2,2,1,0.继续删除序列首项6,对其后的6项每项减1,得到:2,1,1,1,0,-1,得到负数,由于图中不可能存在负度数的顶点,因此该序列是不可图的。

判断此题的数字序列是不是可图的时候,一要判断某次对剩下序列排序后,最大的度数超过了剩下的定点数,二要对最大度数后面的d1个度数减1后,不能出现负数。

代码如下:

1.

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

using namespace std ;

const int maxn = 15 ;

struct vertex{
	int degree ;
	int index  ;
	vertex()
	{
		degree = -1 ;
		index = -1  ;
	}
}v[maxn];

int cmp(const void * a , const void * b)
{
	return ((vertex*)b)->degree - ((vertex*)a)->degree ;
}

int map[maxn][maxn] ;
int test ;
int n ;

void input() ;
void work()  ;

int main()
{
	freopen("data.txt" , "w" , stdout) ;
	scanf("%d" , &test) ;
	while(test--)
	{
		memset(map , 0 , sizeof(map)) ;

		input() ;
		work() ;

		if(test)
			printf("\n") ;

	}

	return 0 ;
}

void input()
{
	int i ;

	scanf("%d" , &n) ;

	for(i = 0 ; i < n ; i ++)
	{
		scanf("%d" , &v[i].degree) ;
		v[i].index = i ;
	}

}

void work()
{
	bool flag = 1 ;

	int k ;
	int i ;
	int j ;
	int m ;
	int s ;

	k = 0 ;

	while(k < n && flag)
	{
		qsort(v+k , n - k , sizeof(v[0]) , cmp) ;

		i = v[k].index  ;
		m = v[k].degree ;
		
		if(m > n - k - 1)
		{
			flag = 0 ;
			break ;
		}
		
		for(j = 1 ; j <= m && flag ; j ++)
		{
			s = v[k+j].index ;

			if(--v[k+j].degree < 0)
			{
				flag = 0 ;
				break ;
			}

			map[i][s] = map[s][i] = 1 ;

		}
		k++ ;
	}

	if(flag)
	{
		printf("YES\n") ;
		
		for(i = 0 ; i < n ; i ++)
		{
			for(j = 0 ; j < n ; j ++)
			{
				printf("%d" , map[i][j]) ;
				
				if(j != n-1)
					printf(" ") ;
			}
			printf("\n") ;
		}
	}
	else printf("NO\n") ;
}
代码2:
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

using namespace std ;

const int maxn = 20 ;

struct Node
{
	int degree ;
	int index  ;
}node[maxn];

int map[maxn][maxn] ;
int n    ;
int test ;
bool falg ;

void input() ;
void work()  ;
void print() ;

int cmp(const void * a , const void * b)
{
	return ((Node *)b)->degree - ((Node *)a)->degree ;
}


int main()
{
	scanf("%d" , &test) ;

	while(test--)
	{
		input() ;
		work()  ;
		print() ;

		if(test)
			printf("\n") ;
	}
	return 0 ;
}

void input()
{
	memset(map , 0 , sizeof(map)) ;

	scanf("%d" , &n) ;

	int i ;

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

void work()
{
	falg = 1 ;

	int k ;
	k = 0 ;
	int m ;
	int q ;
	int i ;

	while(k < n && falg)
	{
		qsort(node , n , sizeof(node[0]) , cmp) ;
		
		m = node[0].degree ;
		q = node[0].index  ;
		
		i = 1 ;

		if(m > n - k - 1)
		{
			falg = 0 ;
			break ;
		}
		

		for( ; i <= m && falg ; i ++)
		{
			if(--node[i].degree < 0)
			{
				falg = 0 ;
				break ;
			}

			map[q][node[i].index] = 1 ;
			map[node[i].index][q] = 1 ;
		}
		node[0].degree = 0 ;

		k++ ;
	}
}

void print()
{
	if(!falg)
	{
		printf("NO\n") ;
		return  ;
	}
	int i ;
	int j ;
	
	printf("YES\n") ;
	for(i = 0 ; i < n ; i ++)
	{
		for(j = 0 ; j < n ; j ++)
		{
			printf("%d", map[i][j]) ;

			if(j!=n-1)
				printf(" ") ;
		}

		printf("\n") ;
	}
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值