zoukankan      html  css  js  c++  java
  • 没有哈密瓜只有哈密顿----图论之哈密顿回路

    老规矩,先来百度一下

    哈密顿图(哈密尔顿图)(英语:Hamiltonian graph,或Traceable graph)是一个无向图,由天文学家哈密顿提出,由指定的起点前往指定的终点,途中经过所有其他节点且只经过一次。在图论中是指含有哈密顿回路的图,闭合的哈密顿路径称作哈密顿回路(Hamiltonian cycle),含有图中所有顶点的路径称作哈密顿路径(Hamiltonian path)。

    通俗来说就是,哈密顿路径就是每个点经过且只经过一次的路径,而最终又回到起点的路径就哈密顿回路。

    哈密顿路径问题在上世纪七十年代初,终于被证明是"NP完备"的。据说具有这样性质的问题,难于找到一个有效的算法。也就是说这个问题,没有实际的算法解决。

    所以我们也就是简单了解一下相关定理。

    (1)若图的最小度不小于顶点数的一半,则图是哈密顿图; 

    (2)若图中每一对不相邻的顶点的度数之和不小于顶点数,则图是哈密顿图。 

    (3)范定理:若图中每对距离为2的点中有一点的度数至少是图的点数的一半,则该图存在哈密尔顿圈。

    哈密顿绕行世界问题HDU - 2181 

    20的3次方,直接暴力dfs跑一遍

     1 #include<cstdio>
     2 int vv[25][5],ans[25],vis[25];
     3 int m,cnt;
     4 void dfs(int n,int u){
     5     ans[n]=u;
     6     if(n==21){
     7         printf("%d: ",cnt++);
     8         for(int i=1;i<=21;i++) printf(" %d",ans[i]);
     9         printf("
    ");
    10         return ;
    11     }
    12     for(int i=1,v;i<=3;i++){
    13         v=vv[u][i];
    14         if(!vis[v]){
    15             if(v==m&&n!=20) continue;
    16             vis[v]=1;
    17             dfs(n+1,v);
    18             vis[v]=0;
    19         }
    20     }
    21 }
    22 int main(){
    23     for(int i=1;i<=20;i++)
    24         for(int j=1;j<=3;j++){
    25             scanf("%d",&vv[i][j]);
    26             for(int k=1;k<j;k++) if(vv[i][k]>vv[i][j]){
    27                 int temp=vv[i][j];vv[i][j]=vv[i][k];vv[i][k]=temp;
    28             }
    29         }
    30     while(scanf("%d",&m)&&m){
    31         for(int i=1;i<=20;i++) vis[i]=0;
    32         cnt=1;
    33         dfs(1,m);
    34     }
    35     return 0;
    36 }
    暴力出奇迹

    A sample Hamilton pathHDU - 3538

    题意:求从0出发的最短哈密顿路径长度,没有就-1

    暴力搜索的话21的21次方,肯定是不可能的,然后我们想一下,每个点走没走的话,那就是1或0,那我们从状态来考虑的就2的21次方-1种状态,也就全0到全1,某位有1就代表这个点走过了。

    所以就成了状压dp,然后路径的话还得记录下当前最后走的点,所以dp[i][j]就是i这个状态下,最后走到的点是j的最短路径。最后就一些细节的判断。

     1 #include<cstdio>
     2 #include<algorithm>
     3 using namespace std;
     4 const int N=1<<21,inf=1e9+7; 
     5 int dp[N][25],dis[25][25],cf2[25]={1},fir[25];
     6 int main(){
     7     int n,m,nn,a,b;
     8     for(int i=1;i<=21;i++) cf2[i]=cf2[i-1]<<1;
     9     while(~scanf("%d%d",&n,&m)){
    10         nn=1<<n;
    11         for(int i=0;i<n;i++) fir[i]=0;
    12         for(int i=0;i<nn;i++)
    13             for(int j=0;j<n;j++)
    14                 dp[i][j]=inf;
    15         for(int i=0;i<n;i++)
    16             for(int j=0;j<n;j++)
    17                 scanf("%d",&dis[i][j]);
    18         for(int i=0;i<m;i++){
    19             scanf("%d%d",&a,&b);
    20             if(a!=0) fir[b]|=cf2[a];
    21         }
    22         dp[1][0]=0;
    23         for(int i=1;i<nn;i++)
    24             for(int j=0;j<n;j++){
    25                 if(dp[i][j]==inf) continue;
    26                 for(int k=1;k<n;k++){
    27                     if((i&cf2[k])!=0||(i&fir[k])!=fir[k]) continue;
    28                     if(dis[j][k]!=-1) dp[i+cf2[k]][k]=min(dp[i+cf2[k]][k],dp[i][j]+dis[j][k]);
    29                 }
    30             }
    31         int ans=inf;
    32         for(int i=0;i<n;i++) if(ans>dp[nn-1][i]) ans=dp[nn-1][i];
    33         if(ans==inf) ans=-1;
    34         printf("%d
    ",ans);
    35     }
    36     return 0;
    37 }
    简单写写
  • 相关阅读:
    Unity3d vector3.forward和transform.forward的区别!
    UGUI实现摇杆
    UGUI实现拼图游戏
    Unity3d打包发布Android程序
    兼容PC和手机触摸代码
    unity3d中Transform组件变量详解
    运算符重载
    扩展方法
    string.Format格式化输出
    网络编程之Socket的TCP协议实现客户端与客户端之间的通信
  • 原文地址:https://www.cnblogs.com/LMCC1108/p/11324389.html
Copyright © 2011-2022 走看看