POJ1659 Frogs' Neighborhood(Havel定理)

xiaoxiao2021-02-28  110

题目:

Frogs' Neighborhood Time Limit: 5000MS Memory Limit: 10000KTotal Submissions: 9932 Accepted: 4152 Special Judge

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

Source

POJ Monthly--2004.05.15 Alcyone@pku

[Submit]   [Go Back]   [Status]   [Discuss]

思路:

这个是Havel定理的应用,关于Havel定理:Havel-Hakimi定理(判断一个序列是否可图)

首先我们对这个序列进行排序,然后找出最大的度数n,然后在这个排好序的序列中对接下来的n个数进行减一,如果出现两种情况就证明这个序列不可图,否则就就在邻接矩阵中把这两个点连起来

①某次对剩下的序列排序后,最大的度数超过了剩下的顶点数

②对最大的度数后面的n个度数进行减1后,出现了负数

如果出现了这两种情况,那么这个序列不可图

我们用一个结构体来记录一个顶点的度数和这个顶点的标号,具体看代码

代码:

#include <cstdio> #include <cstring> #include <string> #include <set> #include <iostream> #include <cmath> #include <stack> #include <queue> #include <vector> #include <algorithm> #define mem(a,b) memset(a,b,sizeof(a)) #define inf 0x3f3f3f3f #define mod 10000007 #define debug() puts("what the fuck!!!") #define N (1010000) #define ll long long using namespace std; struct node { int degree,id;//顶点的度数和标号 } v[20]; int map[20][20]; bool cmp(node a,node b) { return a.degree>b.degree; } int main() { int t,n,flag; scanf("%d",&t); while(t--) { scanf("%d",&n); for(int i=0; i<n; i++) { scanf("%d",&v[i].degree); v[i].id=i;//记录顶点的编号 } mem(map,0); flag=1; for(int k=0; k<n; k++) { sort(v+k,v+n,cmp);//从第k位开始,对整个数组排序 int i=v[k].id;//当前要连的顶点的编号 int d1=v[k].degree;//记录当前这个节点的度数 if(d1>n-k-1)//当当前节点的度数比剩余的顶点数要大的时候,则不存在相连的关系 flag=0; for(int r=1; r<=d1&&flag; r++)//从当前点开始给后面的度数减一 { int j=v[k+r].id;//当前要连的顶点的编号 if(v[k+r].degree<=0)//出现负值代表不存在相连的关系 flag=0; v[k+r].degree--; map[i][j]=map[j][i]=1; } } if(flag) { puts("YES"); for(int i=0; i<n; i++) { for(int j=0; j<n; j++) { if(j)printf(" "); printf("%d",map[i][j]); } puts(""); } } else puts("NO"); if(t) puts(""); } return 0; }

转载请注明原文地址: https://www.6miu.com/read-30421.html

最新回复(0)