图论—青蛙问题

来源:互联网 发布:少女前线敌人数据 编辑:程序博客网 时间:2024/05/18 00:49

青蛙的邻居(Frogs' Neighborhood

题目描述:
未名湖附近共有
n 个大小湖泊 L1,L2, ...,Ln(其中包括未名湖),每个湖泊Li 里住着一只青蛙
Fi1≤in)。如果湖泊Li Lj 之间有水路相连,则青蛙Fi Fj 互称为邻居。现在已知每只青蛙的
邻居数目
x1,x2, ...,xn,请你给出每两个湖泊之间的相连关系。
输入描述:
第一行是测试数据的组数
t0 ≤ t ≤ 20)。每组数据包括两行,第一行是整数n2 ≤n ≤ 10),
第二行是
n 个整数, x1,x2,...,xn0 ≤ xi <n)。

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

样例输入: 样例输出:
           2
            7
            4 3 1 5 4 2 1
            6
            4 3 1 4 2 0



            YES
            0 1 1 1 1 0 0
            1 0 0 1 1 0 0
            1 0 0 0 0 0 0
            1 1 0 0 1 1 1
            1 1 0 1 0 1 0
            0 0 0 1 1 0 0
            0 0 0 1 0 0 0
            NO
分析:
本题的意思实际上是给定一个非负整数序列,问是不是一个可图的序列,也就是说能不能根
据这个序列构造一个图。这需要根据
Havel-Hakimi定理(定理 1.2)中的方法来构图,并在构图
中判断是否出现了不合理的情形。有以下两种不合理的情形:
(1) 某次对剩下序列排序后,最大的度数(设为d1)超过了剩下的顶点数;
(2) 对最大度数后面的 d1 个度数各减1 后,出现了负数。
一旦出现了以上两种情形之一,即可判定该序列不是可图的。
如果一个序列是可图的,本题还要求输出构造得到的图的邻接矩阵,实现思路是:
(1) 为了确保顶点序号与输入时的度数顺序一致,特意声明了一个vertex 结构体,包含了顶点
的度和序号两个成员。
(2) 每次对剩下的顶点按度数从大到小的顺序排序后, 设最前面的顶点 (即当前度数最大的顶
点)序号为
i、度数为 d1,对后面d1 个顶点每个顶点(序号设为j)度数减 1,并连边,即在邻接
矩阵
Edge 中设置 Edge[i][j]Edge[j][i]1 
#include<stdio.h>#include<stdlib.h>#include<string.h>#define N 15struct vertex{int degree;  //定点的度int index;    //定点的序号 }v[N];int cmp(const void *a, const void *b){return ((vertex*)b)->degree - ((vertex*)a)->degree;}int main(){int r,k,p,q;  //循环变量int i,j;  //顶点序号(用于确定图中边的两个顶点) int d1;   //对剩下序列排序后第1个顶点(度数最大的顶点)的度数 int T,n;  //测试数据个数,湖泊个数 int Edge[N][N],flag;   //邻接矩阵。是否存在合理相邻关系的标志 scanf("%d",&T);while(T--){scanf("%d",&n);for(i=0;i<n;i++){scanf("%d",&v[i].degree);v[i].index = i;   //按输入顺序给每个湖泊编号 }memset(Edge,0,sizeof(Edge));flag = 1;for(k=0;k<n&&flag;k++){//对v数组后n-k个元素按非递增顺序排序 qsort(v+k,n-k,sizeof(vertex),cmp);i = v[k].index;   //第k个顶点的序号 d1=v[k].degree;if(d1>n-k-1)   flag = 0;for(r=1;r<=d1&&flag;r++){j=v[k+r].index;   //后边d1个顶点每个顶点的序号 if(v[k+r].degree<=0)  flag=0;v[k+r].degree--;Edge[i][j] = Edge[j][i] = 1;}}if(flag){puts("YES");for(p=0;p<n;p++){for(q=0;q<n;q++){if(q)  printf(" ");printf("%d",Edge[p][q]);}puts("");}}else  puts("NO");if(T)  puts(""); } return 0;}



0 0
原创粉丝点击