圖論-度序列可圖性判斷(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;
		}
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章