poj 2288 (状态压缩+spfa)

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;
        }
}


你可能感兴趣的:(poj 2288 (状态压缩+spfa))