图论-度序列可图性判断(Havel-Hakimi定理)

0、可图:一个非负整数组成的序列如果是某个无向图的度序列,则该序列是可图的。

1、度序列:Sequence Degree,若把图G所有顶点的度数排成一个序列,责成该序列为图G的一个序列。该序列可以是非递增序的、可以是非递减序列、可以是任意无序的。

2、Havel-Hakimi定理:给定一个非负整数序列{d1,d2,…dn},若存在一个无向图使得图中各点的度与此序列一一对应,则称此序列可图化。进一步,若图为简单图,则称此序列可简单图化。

定理描述:由非负整数组成的有限非递增序列,S={d1,d2,d3…dn},当且仅当S1={d2-1,d3-1…d(d1+1),d(d1+2)…dn}也是可图的,也就是说,序列S1也是由非负整数组成的有限非递增序列,S1是由S的删除第一个元素d1之后的前d1个元素分别减一后得到的序列。

(注,Havel-Hakimi定理 讨论的是在非递增序列下判别是否可图的定理)

3、证明略,实例演示:

判断序列S:=6,5,4,3,3,3,2,0 是否可图。

证:a. 删除首元素6,将除去第一个元素后面的6个元素减一,得到:S1 = 4,3,2,2,2,1,0

b.删除首元素4,将除去第一个元素后面的4个元素减一,得到:S2 = 2,1,1,1,1,0

c,删除首元素2,将除去第一个元素后面的2个元素减一,得到:S3 = 0,0,1,1,0

d.重新排序:S4 = 1,1,0,0,0

e.删除首元素1,将除去第一个元素后面的1个元素减一,得到:S3 = 0,0,0,0

则最后得到的是非负序列,证明 序列式可图的!

判断序列S:=7,6,4,3,3,3,2,1 是否可图。

证:a. 删除首元素7,将除去第一个元素后面的7个元素减一,得到:S1 = 6,3,2,2,2,1,0

b.删除首元素6,将除去第一个元素后面的6个元素减一,得到:S2 = 2,1,1,1,0,-1

最后得到的是存在负数的序列,证明 序列式不可图的!


光说不练假把式,来一导poj原题,Frogs’ Neighborhood
在这里插入图片描述
Havel-Hakimi定理的核心部分:

		for (int i = 1; i <= N; i++) {
			for (int j = i + 1; j <= N && a[i].num > 0; j++) {
				a[i].num--;
				a[j].num--;
				g[a[i].id][a[j].id] = g[a[j].id][a[i].id] = 1;
			}
			sort(a + i + 1, a + N + 1, cmp);
			if (a[i].num > 0) { sign = 0; break; }
		}

完整代码:

#define inf 0x3f3f3f3f
#define vec vector<int>
#define P pair<int,int>
#define MAX 15
#define ll long long

struct node {
	int id, num;
};
bool cmp(node n1, node n2) {
	return n1.num > n2.num;
}
int T, N, g[MAX][MAX];
node a[MAX];

int main() {
	cin >> T;
	while (T--) {
		cin >> N;
		int sign = 1;
		memset(g, 0, sizeof(g));
		for (int i = 1; i <= N; i++)cin >> a[i].num, a[i].id = i;
		sort(a + 1, a + N + 1, cmp);
		for (int i = 1; i <= N; i++) {
			for (int j = i + 1; j <= N && a[i].num > 0; j++) {
				a[i].num--;
				a[j].num--;
				g[a[i].id][a[j].id] = g[a[j].id][a[i].id] = 1;
			}
			sort(a + i + 1, a + N + 1, cmp);
			if (a[i].num > 0) { sign = 0; break; }
		}
		if (a[N].num < 0 || !sign) {
			cout << "NO" << endl << endl;
		}
		else {
			cout << "YES" << endl;
			for (int i = 1; i <= N; i++) {
				for (int j = 1; j <= N; j++)
					cout << g[i][j] << ' ';
				cout << endl;
			}
			cout << endl;
		}
	}
}
  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值