ZOJ3332-竞赛图中的哈密顿路

来源:互联网 发布:芒果tv软件下载 编辑:程序博客网 时间:2024/04/25 16:57

竞赛图:图中的任意两点间有且仅有一条有向弧连接

求竞赛图中的哈密顿路的算法:

首先,由数学归纳法可证竞赛图在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;}



原创粉丝点击