现在的位置: 首页 > 综合 > 正文

ZOJ3332-竞赛图中的哈密顿路

2013年12月03日 ⁄ 综合 ⁄ 共 1326字 ⁄ 字号 评论关闭

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

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

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

抱歉!评论已关闭.