问题描述
蒜头君想让你帮他画一个无向图,图中有 n 个顶点,蒜头告诉你这 n 个顶点的度数。为了简化问题,你只需要告诉蒜头君图的邻接矩阵就可以了,图中不存在自环的情况,也就是说邻接矩阵的正对角线均为 0。(矩阵可能不唯一,只要符合要求即可)
输入格式
第一行输入一个整数 n,代表顶点的个数(1≤n≤15),第二行是 n 个整数,分别代表这 n 个顶点的度数。
输出格式
输出一个 n×n 的 01 矩阵,代表图的邻接矩阵。如果没有符合要求的图,则输出“None”。 本题答案不唯一,符合要求的答案均正确。
样例输入1
4
2 3 2 1
样例输出1
0 1 1 0
1 0 1 1
1 1 0 0
0 1 0 0
样例输入2
4
3 2 1 1
样例输出2
None
思路:
关于Havel-Hakimi定理请自行上网寻找。
利用结构体来记录每个节点的编号和度。我们将节点按度数排序,每个节点的度为a[i]。套用公式,对于度数最大的那个点,我们将其与度数次大的a[i]个点用边连起来(即公式中将次大的a[i]个点的度值减一),然后这个点就可以不管了(即公式中删除最大的点)。这样一直做,如果出现有边的度数为负,则这个序列不可图,输出None,若一直减少到所有点度数为0,则得到一个可行的图。
细节:
1、由于只有部分点的度减一,顺序可能会有所不同,每次都应该重新排序。
2、可能会出现度数超过节点数量的情况,也要考虑。
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=20;
int n,l,cur,ma[N][N];
struct Node{
int num,v;
} node[N];
struct cmp{
bool operator()(const Node &a,const Node &b){
return a.v>b.v;
}
};
bool check(){
for(int i=1;i<=n;i++)
if(node[i].v>=n||node[i].v<0) return false;
return true;
}
int main(){
freopen("data.in","r",stdin);
scanf("%d",&l); n=l;
for(int i=1;i<=n;i++){
scanf("%d",&node[i].v);
node[i].num=i;
}
sort(node+1,node+n+1,cmp());
while(n){
cur=0;
if(!check()){
printf("None"); return 0;
}//判断当前情况是否合法
for(int i=2;i-1<=node[1].v;i++){
node[i].v--;
if(!node[i].v) cur++;//用cur记录在连边时度变成0的节点个数
ma[node[1].num][node[i].num]=ma[node[i].num][node[1].num]=1;
}
node[1].v=0;
sort(node+1,node+n+1,cmp());//先排序再减少长度,因为有些有度的节点在后面
n-=1+cur;
}
for(int i=1;i<=l;i++){
for(int j=1;j<=l;j++)
printf("%d ",ma[i][j]);
printf("\n");
}
return 0;
}
本文介绍如何根据给定的顶点度数序列构造一个无向图的邻接矩阵,使用Havel-Hakimi定理并通过C++实现,解决实际问题。
&spm=1001.2101.3001.5002&articleId=80466165&d=1&t=3&u=e58124f2ecaf466194d296207ff385ae)
1267

被折叠的 条评论
为什么被折叠?



