zoukankan      html  css  js  c++  java
  • 最短Hamilton路径

    题目link:https://www.acwing.com/problem/content/93/

    注意,本题解中,存点为 $0$ ~ $n$ $-$ $1$ ,二进制最低位为第 $0$ 位。

    二进制压缩状态,第 $a$ 位为 $1$ 表示第 $a$ 个点走过了,否则没有走过。

    考虑朴素的 SPFA 做法,需要记录走到的点。此题还需要记录当前状态,即哪些 走/没走 过(二进制来表示)。

    设 $dis[x][u]$ 表示当前状态为 $x$ ,从 $0$ 到 $u$ 的最短路径(含义见上)。设 $u$ 通过第 $i$ 条边到达了点 $k$ 。

    对于每个 $dis[x][u]$ 在 SPFA 中更新 $k$ 的操作,除了需要判断是否满足最短路之外,还需要判断当前状态是否走过 $k$ ,用二进制运算可以轻松算出,即判断 $x$ & $(1$ $<<$ $k)$ $==$ $0$ 。然后在更新中, $k$ 的状态容易得出为 $x$ $|$ $(1$ $<<$ $k)$ 。

    最后结果为当所有点都经过,并且结束点为 $n$ $-$ $1$ ,即 $dis[(1$ $<<$ $n)$ $-$ $1][n$ $-$ $1]$ 。

    代码就很简单了,注意数组大小,不要 MLE 。

     1 #include <bits/stdc++.h>
     2 #define INF 0x3f3f3f3f
     3 using namespace std;
     4 int n, head[21], vis[(1 << 20) + 10][21], dis[(1 << 20) + 10][21], num;
     5 struct node {int next, to, val;}stu[810];
     6 void add(int x, int y, int z) {stu[++num].next = head[x]; stu[num].to = y; stu[num].val = z; head[x] = num;}
     7 void spfa()
     8 {
     9     queue < pair < int, int > > pru;
    10     memset(dis, INF, sizeof(dis));
    11     pru.push(make_pair(1, 0));
    12     dis[1][0] = 0, vis[1][0] = 1;
    13     while(!pru.empty())
    14     {
    15         int x = pru.front().first, u = pru.front().second;
    16         pru.pop(); vis[x][u] = 0;
    17         for(int i = head[u]; i; i = stu[i].next)
    18         {
    19             int k = stu[i].to;
    20             if((x & (1 << k)) == 0 && dis[x | (1 << k)][k] > dis[x][u] + stu[i].val)//== 和 & 的优先级!!!
    21             {
    22                 dis[x | (1 << k)][k] = dis[x][u] + stu[i].val;
    23                 if(!vis[x | (1 << k)][k]) vis[x | (1 << k)][k] = 1, pru.push(make_pair(x | (1 << k), k));
    24             }
    25         }
    26     }
    27     return;
    28 }
    29 int main()
    30 {
    31     scanf("%d", &n);
    32     for(int i = 0; i < n; ++i)
    33         for(int j = 0, x; j < n; ++j)
    34             scanf("%d", &x), add(i, j, x), add(j, i, x);
    35     spfa();
    36     printf("%d", dis[(1 << n) - 1][n - 1]);
    37     return 0;
    38 }
  • 相关阅读:
    Bootstrap 学习笔记 之网格系统
    自定义属性建立匹配、对应关系——JS学习笔记2015-5-27(第40天)
    CSS那些事儿——关于如何提高编写代码的能力
    自定义属性,匹配数组内容——JS学习笔记2015-5-26(第39天)
    css学习之幻灯片(轮播图)原理
    自定义属性,第一节——JS学习笔记2015-5-25(第38天)
    字体不同,造成的显示异常
    浮动相关理解,以及清除浮动的方法总结
    border实现三角箭头
    go mode
  • 原文地址:https://www.cnblogs.com/qqq1112/p/14279227.html
Copyright © 2011-2022 走看看