Codeforces Round #321 (Div. 2) Kefa and Dishes 状压+spfa

原题链接:http://codeforces.com/contest/580/problem/D

题意:

给你一些一个有向图,求不超过m步的情况下,能获得的最大权值和是多少,点不能重复走。

题解:

令$dp[u][s]$为在节点u的时候状态是s的最大值。利用spfa的松弛操作来转移。

代码:

#include<iostream>
#include<cstring>
#include<vector>
#include<algorithm>
#include<queue>
#define MAX_S 1<<19
#define MAX_N 22
using namespace std;

typedef long long ll;

struct edge {
public:
    int to;
    ll cost;

    edge(int t, ll c) : to(t), cost(c) { }

    edge() { }
};

vector<edge> G[MAX_N];
ll g[MAX_N][MAX_N];
ll a[MAX_N];
int n,m,k;

int ones[MAX_S];

ll dp[MAX_N][MAX_S];

struct node {
public:
    ll s;
    int u;

    node(ll ss, int uu) : s(ss), u(uu) { }

    node() { }
};

queue<node> que;
bool inQue[MAX_N][MAX_S];

int main() {
    cin.sync_with_stdio(false);
    cin >> n >> m >> k;
    for (int i = 0; i < (1 << n); i++) {
        int x = i;
        while (x)ones[i] += (x & 1), x >>= 1;
    }
    for (int i = 0; i < n; i++)
        cin >> a[i];
    for (int i = 0; i < k; i++) {
        int x, y;
        ll c;
        cin >> x >> y >> c;
        x--, y--;
        g[y][x] = c;
    }
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            G[i].push_back(edge(j, g[i][j]));
    ll ans = 0;
    for (int i = 0; i < n; i++) {
        dp[i][1 << i] = a[i];
        que.push(node(1 << i, i));
        inQue[i][1 << i] = 1;
    }
    while (!que.empty()) {
        node now = que.front();
        que.pop();
        ll s = now.s;
        int u = now.u;
        inQue[u][s] = 0;
        for (int i = 0; i < G[u].size(); i++) {
            int v = G[u][i].to;
            ll c = G[u][i].cost;
            if (s & (1 << v))continue;
            ll ns = s | (1 << v);
            if (ones[ns] > m)continue;
            if (dp[v][ns] < dp[u][s] + a[v] + c) {
                dp[v][ns] = dp[u][s] + a[v] + c;
                que.push(node(ns, v));
                inQue[v][ns] = 1;
            }
        }
    }
    for (int i = 0; i < n; i++)
        for (int s = 0; s < (1 << n); s++)
            if (ones[s] == m)
                ans = max(ans, dp[i][s]);
    cout << ans << endl;
    return 0;
}
原文地址:https://www.cnblogs.com/HarryGuo2012/p/4831101.html