竞赛图和哈密顿回路
结论
对于一个竞赛图,一定有哈密顿通路
对于一个强连通竞赛图,一定有哈密顿回路
竞赛图缩点后肯定是一条链
哈密顿通路证明
给出伪代码
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 o i o r),考虑从中间找到满足 (t o i o nxt[t]) 的位置然后把 i 插入即可,容易发现一定存在这样一个位置。如果目前只有两个点,显然成立。如果不是,那么从 l 开始,满足 (l o i),如果有 (i o nxt[l]) 直接满足,否则满足 (nxt[l] o 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 o n $ 中至少有一个点有连向 1 的边,否则不会强连通,设它为 x,现在我们就有了一个 (1 o x o 1) 的哈密顿回路。现在考虑一个一个加入下一个点,考虑 (x+1) 的若干中情况。
- 有边 (x + 1 o 1),让 (x) 连 (x+1),(x+1) 连 1 即可
- (x+1) 对所有的 (1 o x) 都有边,将 (x+1) 和 (x+2) 这个线段看作整体,继续考量 (x+2),这时候只要 (x+2) 对 (1 o x) 有反向边就可以直接插入。由于强连通,所以不可能剩下的点都没有反向边。
- 否则一定存在 (t o x o nxt[t]),可以画图理解一下,和上面证哈密顿通路的过程是一样的。
竞赛图缩点证明
假设缩点完毕,容易发现一个联通分量到另一个连通分量肯定有限制关系,所以可以变成一条链。