没有哈密瓜只有哈密顿----图论之哈密顿回路

老规矩,先来百度一下

哈密顿图(哈密尔顿图)(英语: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("\n");
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\n",ans);
35     }
36     return 0;
37 }
简单写写

 

posted @ 2019-08-08 22:51  新之守护者  阅读(685)  评论(0编辑  收藏  举报