競賽圖和哈密頓回路
結論
對於一個競賽圖,一定有哈密頓通路
對於一個強連通競賽圖,一定有哈密頓回路
競賽圖縮點后肯定是一條鏈
哈密頓通路證明
給出偽代碼
void work() {
int l = r = 1;
for (int i = 2;i <= n; i++) {
if (ed[i][l]) nxt[i] = l, l = i;
else if (ed[r][i]) nxt[r] = i, r = i;
else for (int j = l; ; j = nxt[j])
if (a[i][nxt[j]]) { nxt[i] = nxt[j], nxt[j] = i; break; }
}
}
我們維護 1 ~ i-1 的哈密頓路徑,考慮插入 i,如果可以接到頭尾直接加入即可。否則滿足有路徑 \(l \to i \to r\),考慮從中間找到滿足 \(t \to i \to nxt[t]\) 的位置然后把 i 插入即可,容易發現一定存在這樣一個位置。如果目前只有兩個點,顯然成立。如果不是,那么從 l 開始,滿足 \(l \to i\),如果有 \(i \to nxt[l]\) 直接滿足,否則滿足 \(nxt[l] \to i\) 這樣還是原來的問題,這樣就可以用數學歸納法證了。
哈密頓回路證明
//這個部分最好畫圖理解,圖是一個環長一條尾巴的樣子。
r=0;//這里是緊接着上面找完通路。先把r置為0表示還沒有找到初始的環。
for(int i=l;i;i=nxt[i])//r是環上最靠近鏈的點,r->l是環上的邊,r->nxt[r]是鏈上的邊。
if(r){//嘗試在環中插入點i
for(int j=l,k=r;;k=j,j=nxt[j]){
if(a[i][j]){//在環上找到一個可以作為nxt[i]的點。
nxt[k]=nxt[r];//j作為了i的后繼,那么本來j的前驅k就要另找一個后繼了。(這里注意nxt[r]不一定是i,因為可能前面的一些點沒有插入成功)
if(k!=r)nxt[r]=l;//本來沒有連上的環上的邊要連上(k=r的話r的后繼在上一句話已經改了,不是l了)
l=j,r=i;break;//根據l和r的定義修改l和r
}
if(j==r)break;//確實有可能當前無法插入,但是后面的點一定會有插入成功的,那時這個點也就會進入環內。
}
}
else if(a[i][l])r=i;//這里找到了初始的環
nxt[r]=l;//這里把最后一條邊連上。
這個是學長的代碼,簡要說明一下
強連通的限制保證了不會有一個點向其他點都是正向邊或反向邊。
先找到一條哈密頓通路,容易發現 $2 \to n $ 中至少有一個點有連向 1 的邊,否則不會強連通,設它為 x,現在我們就有了一個 \(1 \to x \to 1\) 的哈密頓回路。現在考慮一個一個加入下一個點,考慮 \(x+1\) 的若干中情況。
- 有邊 \(x + 1 \to 1\),讓 \(x\) 連 \(x+1\),\(x+1\) 連 1 即可
- \(x+1\) 對所有的 \(1\to x\) 都有邊,將 \(x+1\) 和 \(x+2\) 這個線段看作整體,繼續考量 \(x+2\),這時候只要 \(x+2\) 對 \(1 \to x\) 有反向邊就可以直接插入。由於強連通,所以不可能剩下的點都沒有反向邊。
- 否則一定存在 \(t \to x \to nxt[t]\),可以畫圖理解一下,和上面證哈密頓通路的過程是一樣的。
競賽圖縮點證明
假設縮點完畢,容易發現一個聯通分量到另一個連通分量肯定有限制關系,所以可以變成一條鏈。