竞赛图:图中的任意两点间有且仅有一条有向弧连接
求竞赛图中的哈密顿路的算法:
首先,由数学归纳法可证竞赛图在n>=2时必存在哈密顿路;
(1)n=2时显然;
(2)假设n=k时,结论成立,哈密顿路为V1,V2,...,Vi,...,Vk;
现添加第k+1个结点,若存在弧<Vi,Vk+1>和弧<Vk+1,Vi+1>,则可得哈密顿回路V1,V2,...,Vi,Vk+1,Vi+1,...,Vk;
若不存在上述的vi,考虑到Vk+1与v1~vk的连通状况,则只有下面种原哈密顿路的情况:
1.所有的Vi(1<i<k)与Vk+1的弧的方向都是<Vi,Vk+1>,那么可得哈密顿回路V1,V2,...,Vi,...,Vk,Vk+1;
2.所有的Vi(1<i<k)与Vk+1的弧的方向都是<Vk+1,Vi>,那么可得哈密顿回路Vk+1,V1,V2,...,Vi,...,Vk;
3.存在一个中间结点m,使得所有的Vi(1<=i<=m)与Vk+1的弧方向为<Vk+1,Vi>,所有的Vj(m<j<=k)与Vk+1的弧的方向为<Vj,Vk+1>,这时依然可以构造哈密顿路 V1,V2,...,Vi,...,Vk,Vk+1;
(3)那么算法也显然了。
#include <cstdio> #include <cstring> #include <iostream> #include <cmath> #include <algorithm> using namespace std; const int NN=110; int n,map[NN][NN]; struct node { int x; struct node *next; }*h; inline void clr(node *p) { node *pp; while (p) { pp=p; p=p->next; delete(pp); } } inline bool ok(int i,int j,int k) { return (map[i][j] && map[j][k]); } void solve() { node *p1,*p2; clr(h); h=new node; h->x=0; h->next=NULL; for (int i=1; i<=n; i++) { p1=h; while (p1->next && !ok(p1->x,i,p1->next->x)) p1=p1->next; p2=new node; p2->x=i; p2->next=p1->next; p1->next=p2; } p1=h->next; for (int i=1; i<n; i++) { printf("%d ",p1->x); p1=p1->next; } printf("%d\n",p1->x); } int main() { int cas,u,v; scanf("%d",&cas); while (cas--) { scanf("%d",&n); if (n==1) { printf("1\n"); continue; } for (int i=1; i<=n; i++) map[0][i]=true; for (int i=1; i<=n*(n-1)/2; i++) { scanf("%d%d",&u,&v); map[u][v]=true; map[v][u]=false; } solve(); } return 0; }