[hdu5418 Victor and World]floyd + 状压DP 或 SPFA

题意:给n个点,m条边,每次只能沿边走,花费为边权值,求从1出发经过所有其它点≥1次最后回到1的最小花费。

思路:

  1. 状压DP。先用Floyd得到任意两点间的最短距离,转移时沿两个点的最短路转移。此时的状态表示为dp[i][j]:“落脚点集合为i,最后停在j”的方案数;而不是“访问过的点的集合为i,最后停在j”的方案数。
  2. SPFA。每个状态保存访问过的点的集合,以及最后停留的位置,然后SPFA即可。

 

floyd + 状压DP

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
#pragma comment(linker, "/STACK:10240000")
#include <map>
#include <set>
#include <cmath>
#include <ctime>
#include <deque>
#include <queue>
#include <stack>
#include <vector>
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

#define X                   first
#define Y                   second
#define pb                  push_back
#define mp                  make_pair
#define all(a)              (a).begin(), (a).end()
#define fillchar(a, x)      memset(a, x, sizeof(a))
#define fillarray(a, b)     memcpy(a, b, sizeof(a))

typedef long long ll;
typedef pair<int, int> pii;
typedef unsigned long long ull;

#ifndef ONLINE_JUDGE
void RI(vector<int>&a,int n){a.resize(n);for(int i=0;i<n;i++)scanf("%d",&a[i]);}
void RI(){}void RI(int&X){scanf("%d",&X);}template<typename...R>
void RI(int&f,R&...r){RI(f);RI(r...);}void RI(int*p,int*q){int d=p<q?1:-1;
while(p!=q){scanf("%d",p);p+=d;}}void print(){cout<<endl;}template<typename T>
void print(const T t){cout<<t<<endl;}template<typename F,typename...R>
void print(const F f,const R...r){cout<<f<<", ";print(r...);}template<typename T>
void print(T*p, T*q){int d=p<q?1:-1;while(p!=q){cout<<*p<<", ";p+=d;}cout<<endl;}
#endif
template<typename T>bool umax(T&a, const T&b){return b<=a?false:(a=b,true);}
template<typename T>bool umin(T&a, const T&b){return b>=a?false:(a=b,true);}

const double PI = acos(-1.0);
const int INF = 0x3f3f3f3f;
const double EPS = 1e-12;

/* -------------------------------------------------------------------------------- */

const int maxn = 16;

int e[maxn][maxn], dist[maxn][maxn], dp[1 << maxn][maxn];
int n;

void add(int u, int v, int w) {
    umin(e[u][v], w);
}

void work() {
    fillchar(dp, 0x3f);
    for (int i = 0; i < n; i ++) {
        for (int j = 0; j < n; j ++) {
            dist[i][j] = e[i][j];
        }
    }
    for (int k = 0; k < n; k ++) {
        for (int i = 0; i < n; i ++) {
            for (int j = 0; j < n; j ++) {
                if (k != i && k != j && i != j) {
                    umin(dist[i][j], dist[i][k] + dist[k][j]);
                }
            }
        }
    }
    dp[1][0] = 0;
    for (int i = 2; i < (1 << n); i ++) {
        for (int j = 0; j < n; j ++) {
            if (i & (1 << j)) {
                for (int k = 0; k < n; k ++) {
                    if (k != j) if (i & (1 << k)) {
                        umin(dp[i][j], dp[i ^ (1 << j)][k] + dist[k][j]);
                    }
                }
            }
        }
    }
    int ans = dp[(1 << n) - 1][0];
    for (int i = 1; i < n; i ++) {
        umin(ans, dp[(1 << n) - 1][i] + dist[i][0]);
    }
    cout << ans << endl;
}

int main() {
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
#endif // ONLINE_JUDGE
    int T, u, v, w, m;
    cin >> T;
    while (T --) {
        cin >> n >> m;
        fillchar(e, 0x3f);
        for (int i = 0; i < m; i ++) {
            scanf("%d%d%d", &u, &v, &w);
            u --; v --;
            add(u, v, w);
            add(v, u, w);
        }
        work();
    }
    return 0;
}

SPFA:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
#pragma comment(linker, "/STACK:10240000")
#include <map>
#include <set>
#include <cmath>
#include <ctime>
#include <deque>
#include <queue>
#include <stack>
#include <vector>
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

#define X                   first
#define Y                   second
#define pb                  push_back
#define mp                  make_pair
#define all(a)              (a).begin(), (a).end()
#define fillchar(a, x)      memset(a, x, sizeof(a))
#define fillarray(a, b)     memcpy(a, b, sizeof(a))

typedef long long ll;
typedef pair<int, int> pii;
typedef unsigned long long ull;

#ifndef ONLINE_JUDGE
void RI(vector<int>&a,int n){a.resize(n);for(int i=0;i<n;i++)scanf("%d",&a[i]);}
void RI(){}void RI(int&X){scanf("%d",&X);}template<typename...R>
void RI(int&f,R&...r){RI(f);RI(r...);}void RI(int*p,int*q){int d=p<q?1:-1;
while(p!=q){scanf("%d",p);p+=d;}}void print(){cout<<endl;}template<typename T>
void print(const T t){cout<<t<<endl;}template<typename F,typename...R>
void print(const F f,const R...r){cout<<f<<", ";print(r...);}template<typename T>
void print(T*p, T*q){int d=p<q?1:-1;while(p!=q){cout<<*p<<", ";p+=d;}cout<<endl;}
#endif
template<typename T>bool umax(T&a, const T&b){return b<=a?false:(a=b,true);}
template<typename T>bool umin(T&a, const T&b){return b>=a?false:(a=b,true);}

const double PI = acos(-1.0);
const int INF = 0x3f3f3f3f;
const double EPS = 1e-12;

/* -------------------------------------------------------------------------------- */

const int maxn = 16;

int n;
int e[maxn][maxn], d[maxn][1 << maxn], vis[maxn][1 << maxn];

void add(int u, int v, int w) {
    u --;
    v --;
    umin(e[u][v], w);
}

bool relax(pii u, pii v, int w) {
    if (d[v.X][v.Y] > d[u.X][u.Y] + w) {
        d[v.X][v.Y] = d[u.X][u.Y] + w;
        return true;
    }
    return false;
}

void work() {
    fillchar(vis, 0);
    fillchar(d, 0x3f);
    queue<pii> Q;
    Q.push(mp(0, 1));
    d[0][1] = 0;
    vis[0][1] = true;
    while (!Q.empty()) {
        pii H = Q.front(); Q.pop();
        vis[H.X][H.Y] = false;
        for (int i = 0; i < n; i ++) {
            if (e[H.X][i] < INF) {
                pii P = mp(i, H.Y | (1 << i));
                if (relax(H, P, e[H.X][i]) && !vis[P.X][P.Y]) {
                    vis[P.X][P.Y] = true;
                    Q.push(P);
                }
            }
        }
    }
    cout << d[0][(1 << n) - 1] << endl;
}

int main() {
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
#endif // ONLINE_JUDGE
    int T, u, v, w, m;
    cin >> T;
    while (T --) {
        cin >> n >> m;
        fillchar(e, 0x3f);
        for (int i = 0; i < m; i ++) {
            scanf("%d%d%d", &u, &v, &w);
            add(u, v, w);
            add(v, u, w);
        }
        work();
    }
    return 0;
}
posted @ 2015-08-23 05:00  jklongint  阅读(255)  评论(0编辑  收藏  举报