[hackerrank]Walking the Longest Path (Approximation Problem)

来源:互联网 发布:safari淘宝不显示图片 编辑:程序博客网 时间:2024/05/21 11:14

题目大意

求一条尽可能长的哈密顿路径,并输出。
保证存在长度为n的哈密顿路径。
你找的哈密顿路径长度至少为n*0.95且合法即算对。

随机算法

这个不可做,因此考虑随机算法。
我们随机它个800次!
每次随机一个中间点w,然后从w拓展出两条不相交的路径作为本次搜出的哈密顿路径。
每个点i用一个d[i]表示i有多少出边连向的点不在目前找到的哈密顿路径中,接下来d用度数称呼。
每次对于当前点k,如果k存在一个相连的不在哈密顿路径中的度数为1的点,那么我们就将其加入哈密顿路径中,然后更新当前点。
这是为什么呢?因为我们希望尽可能捅进那条可行长度为n的链。(纯口胡)
找不到度数为1的点,就随机一个相邻不在哈密顿路径中的点走过去。
做两次上述算法就得到一条哈密顿路径。
重复这个过程800次(或更多或更少,随你便),以最长的哈密顿路径作为答案。

#include<cstdio>#include<algorithm>#define fo(i,a,b) for(i=a;i<=b;i++)#define fd(i,a,b) for(i=a;i>=b;i--)using namespace std;typedef long long ll;const int maxn=10000+10,maxm=100000+10;int ans[maxn],d[maxn],now[maxn],a[maxn],b[maxn],c[maxn];int h[maxn],go[maxm*2],nex[maxm*2];bool bz[maxn];int i,j,k,w,l,t,n,m,tot,ca;int read(){    int x=0,f=1;    char ch=getchar();    while (ch<'0'||ch>'9'){        if (ch=='-') f=-1;        ch=getchar();    }    while (ch>='0'&&ch<='9'){        x=x*10+ch-'0';        ch=getchar();    }    return x*f;}int random(int x){    int t=rand()%10000;    t=t*10000+rand()%10000;    return t%x;}void add(int x,int y){    d[y]++;    go[++tot]=y;    nex[tot]=h[x];    h[x]=tot;}int main(){    n=read();m=read();    fo(i,1,m){        j=read();k=read();        add(j,k);add(k,j);    }    ca=800;    while (ca--){        fo(i,1,n) now[i]=d[i],bz[i]=0;        k=random(n)+1;        w=k;        a[a[0]=1]=k;        bz[k]=1;        while (1){            c[0]=0;            j=0;            t=h[k];            while (t){                now[go[t]]--;                if (now[go[t]]==1&&!bz[go[t]]) j=go[t];                if (!bz[go[t]]) c[++c[0]]=go[t];                t=nex[t];            }            if (!c[0]) break;            if (!j) j=c[random(c[0])+1];            bz[j]=1;            a[++a[0]]=j;            k=j;        }        k=w;        b[b[0]=1]=k;        while (1){            c[0]=0;            j=0;            t=h[k];            while (t){                if (k!=w) now[go[t]]--;                if (now[go[t]]==1&&!bz[go[t]]) j=go[t];                if (!bz[go[t]]) c[++c[0]]=go[t];                t=nex[t];            }            if (!c[0]) break;            if (!j) j=c[random(c[0])+1];            bz[j]=1;            b[++b[0]]=j;            k=j;        }        if (a[0]+b[0]-1>ans[0]){            ans[0]=a[0]+b[0]-1;            fd(i,a[0],1) ans[a[0]-i+1]=a[i];            fo(i,2,b[0]) ans[a[0]+i-1]=b[i];        }    }    printf("%d\n",ans[0]);    fo(i,1,ans[0]) printf("%d ",ans[i]);    printf("\n");}
0 0