dp[i][j][k] 表示状态为i (二进制第k位为1表示第(k+1)顶点在当前路径里),倒数第二个点为j,最后一个点为k的最大值
之后类似spfa求最常路一样求解,初始把所有单个顶点的状态加入队列里,n==1是特判。
/* * ===================================================================================== * * Filename: 2288.cpp * Version: 1.0 * Created: 2013-08-28 21:53:35 * Revision: none * Compiler: GNU C++ * * Just like you,wait you forever~~ * * ===================================================================================== */ #include <set> #include <map> #include <list> #include <queue> #include <stack> #include <cmath> #include <string> #include <cstdio> #include <vector> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define PB push_back #define SIZE(x) (int)x.size() #define clr(x,y) memset(x,y,sizeof(x)) #define MP(x,y) make_pair(x,y) #define reads(n) scanf ("%s", n) #define ALL(t) (t).begin(),(t).end() #define FOR(i,n,m) for (int i = n; i <= m; i ++) #define ROF(i,n,m) for (int i = n; i >= m; i --) #define IT iterator #define FF first #define SS second typedef long long ll; typedef unsigned int uint; typedef unsigned long long ull; typedef vector<int> vint; typedef vector<string> vstring; typedef pair<int, int> PII; void RI (int& x){ x = 0; char c = getchar (); while (c == ' '||c == '\n') c = getchar (); bool flag = 1; if (c == '-'){ flag = 0; c = getchar (); } while (c >= '0' && c <= '9'){ x = x * 10 + c - '0'; c = getchar (); } if (!flag) x = -x; } void RII (int& x, int& y){RI (x), RI (y);} void RIII (int& x, int& y, int& z){RI (x), RI (y), RI (z);} /**************************************END define***************************************/ const ll mod = 1e9+7; const ll LINF = 1e18; const int INF = 1e9; const double EPS = 1e-8; const int N = 14; pair<ll, ll> dp[1<<(N-1)][N][N]; int w[N]; bool g[N][N], vis[1<<(N-1)][N][N]; void init (){ clr (dp, 0), clr (g, 0), clr (vis, 0); } int main (){ int T; RI (T); while (T --){ init (); int n, m; RII (n, m); FOR (i, 1, n){ RI (w[i]); } while (m --){ int u, v; RII (u, v); g[u][v] = g[v][u] = 1; } queue<pair<PII, int> > q; FOR (i, 1, n){ int val = (1<<(i-1)); dp[val][0][i].FF = w[i]; dp[val][0][i].SS = 1; vis[val][0][i] = 1; q.push (MP (MP (val, 0), i)); } while (SIZE (q)){ pair<PII, int> t = q.front (); q.pop (); int x = t.FF.FF, y = t.FF.SS, z = t.SS; vis[x][y][z] = 0; FOR (i, 1, n){ if (g[z][i]&&(((1<<i-1)&x) == 0)){ ll val = dp[x][y][z].FF + w[i] + w[z] * w[i]; if (g[y][i]) val += w[y]*w[z]*w[i]; int tx = x|(1<<i-1), ty = z, tz = i; if (val > dp[tx][ty][tz].FF){ dp[tx][ty][tz].FF = val; dp[tx][ty][tz].SS = dp[x][y][z].SS; if (!vis[tx][ty][tz]){ q.push (MP (MP (tx, ty), tz)); vis[tx][ty][tz] = 1; } }else if (val == dp[tx][ty][tz].FF){ dp[tx][ty][tz].SS += dp[x][y][z].SS; if (!vis[tx][ty][tz]){ vis[tx][ty][tz] = 1; q.push (MP (MP (tx, ty), tz)); } } } } } int sta = (1<<n)-1; ll maxx = 0, num = 0; FOR (i, 0, n){ FOR (j, 1, n){ if (dp[sta][i][j].FF > maxx){ maxx = dp[sta][i][j].FF; num = dp[sta][i][j].SS; }else if (dp[sta][i][j].FF == maxx){ num += dp[sta][i][j].SS; } } } cout << maxx << " " << num/2 + num%2 << endl; } }