poj1659题解

 

Description

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

Input

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

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
 

 

 

要求:判断序列是否可图——可根据havel算法 

havel算法:将递减序列 首元素个后面的元素相应减一,再次排列。如果最终次序列可以全部为零,则该序列可以是可图的。否则不可图。

理解的不难 但是在写的时候,发现自己可能又要用三重循环实现。而且条件很多,我一般不会让自己取用判断条件很多的情况,会把自己绕进去。

 

后来我学历了网上的代码。作者提前找到了排序序列区间的规律 ,因此可以利用双重循环实现。

而且在二重循环的次数中利用当前序列最大值的个数 控制的。

 

学习代码:

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

using namespace std;
struct Point{
	int index;
	int weight;
}; 

int tag[200][200];
struct Point map[20];
bool cmp ( Point a, Point b){
	return a.weight > b.weight;
}
int  main(){
	int t,n,flag ; 
	cin >>t;
	while(t--){
		cin >> n ;
		flag = 1; 
		memset(tag,0,sizeof(tag));
		for(int i =0 ; i <n;++i){
			cin >> map[i].weight;
			map[i].index = i ;// 
		}
		for(int i = 0; i < n ;++i){
			sort(map+i,map+n,cmp);//
				if(map[n-1].weight < 0){//排序之后最小的在后面,因此总是判断最后一个是否为负数 
					flag = 0;
					break; 
				}
				if(map[i].weight==0){//
					break;//结点都是零的状态 
				}
				else {
					for(int j = i+1 ; map[i].weight > 0; ++j){ //
					map[i].weight--;// 
					map[j].weight--;
					tag[map[i].index][map[j].index] = 1;//对于邻接矩阵的存储我是靠记忆的
					tag[map[j].index][map[i].index] = 1; 
				}
			}
		} 
		if(flag){
			cout << "Yes"<<endl;
			for(int  i =0 ; i< n ;++i){
				for (int j= 0; j < n ;++j){
					if(j==0){
						cout <<tag[i][j];
					} 
					else {
						cout <<" "<<tag[i][j];
					}
				}
				cout << endl;
			} 
		}
		else {
		cout <<"No"<<endl;
		} 
		
	}
	return 0;
}
for(int i = 0; i < n ;++i){
			sort(map+i,map+n,cmp);//
				if(map[n-1].weight < 0){//排序之后最小的在后面,因此总是判断最后一个是否为负数 
					flag = 0;
					break; 
				}
				if(map[i].weight==0){//
					break;//结点都是零的状态 
				}
				else {
					for(int j = i+1 ; map[i].weight > 0; ++j){ //
					map[i].weight--;// 
					map[j].weight--;
					tag[map[i].index][map[j].index] = 1;
					tag[map[j].index][map[i].index] = 1; 
				}
			}
		} 

我认为以上是核心代码部分,一重循环中要对最后一个元素进行判断是否负数,我在想会不会遗漏呢?后来想进行排序,那最小的会在后面。

另外一点是,当当前结点也就是最大值是零的状态 就代表判断结束 则是可图的

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值