【斯坦纳树】 HDOJ 4085 Peach Blossom Spring

额。。。斯坦纳树参见:http://endlesscount.blog.163.com/blog/static/821197872012525113427573

#include <iostream>
#include <queue> 
#include <stack> 
#include <map> 
#include <set> 
#include <bitset> 
#include <cstdio> 
#include <algorithm> 
#include <cstring> 
#include <climits>
#include <cstdlib>
#include <cmath>
#include <time.h>
#define maxn 2005
#define maxm 4005
#define eps 1e-7
#define mod 1000000007
#define INF 0x3f3f3f3f
#define PI (acos(-1.0))
#define lowbit(x) (x&(-x))
#define mp make_pair
#define ls o<<1
#define rs o<<1 | 1
#define lson o<<1, L, mid 
#define rson o<<1 | 1, mid+1, R
#define pii pair<int, int>
#pragma comment(linker, "/STACK:16777216")
typedef long long LL;
typedef unsigned long long ULL;
//typedef int LL;
using namespace std;
LL qpow(LL a, LL b){LL res=1,base=a;while(b){if(b%2)res=res*base;base=base*base;b/=2;}return res;}
LL powmod(LL a, LL b){LL res=1,base=a;while(b){if(b%2)res=res*base%mod;base=base*base%mod;b/=2;}return res;}
// head

struct Edge
{
	int v, w;
	Edge *next;
}*H[maxn], E[maxm], *edges;

queue<pair<int, int> > q;
bool in[55][maxn];
int d[55][maxn];
int dp[maxn];
int p[55];
int n, m, k, o;

void addedges(int u, int v, int w)
{
	edges->v = v;
	edges->w = w;
	edges->next = H[u];
	H[u] = edges++;
}

void init()
{
	edges = E;
	memset(H, 0, sizeof H);
	memset(p, 0, sizeof p);
	memset(in, 0, sizeof in);
	memset(d, INF, sizeof d);
	memset(dp, INF, sizeof dp);
}

void read()
{
	int u, v, w;
	scanf("%d%d%d", &n, &m, &k);
	while(m--) {
		scanf("%d%d%d", &u, &v, &w);
		addedges(u, v, w);
		addedges(v, u, w);
	}
	for(int i = 1; i <= k; i++) {
		p[i] = 1 << i - 1;
		p[n-i+1] = 1 << k + i - 1;
		d[i][p[i]] = d[n-i+1][p[n-i+1]] = 0;
	}
	o = 1 << k * 2;
}

bool update(int x, int y, int w)
{
	if(d[x][y] > w) {
		d[x][y] = w;
		return true;
	}
	else return false;
}

bool check(int x)
{
	int res = 0;
	for(int i = 0; x; x >>= 1, i++)
		res += (x & 1) * (i < k ? 1 : -1);
	return res == 0;
}

void spfa()
{
	while(!q.empty()) {
		int x = q.front().first, y = q.front().second;
		q.pop(), in[x][y] = false;
		for(Edge *e = H[x]; e; e = e->next) {
			int v = e->v, w = e->w;
			if(update(v, y | p[v], w + d[x][y]) && !in[v][y]) {
				in[v][y] = true;
				q.push(mp(v, y));
			}
		}
	}
}

void work()
{
	for(int y = 0; y < o; y++) {
		for(int x = 1; x <= n; x++) {
			for(int i = (y - 1) & y; i; i = (i - 1) & y)
				d[x][y] = min(d[x][y], d[x][i | p[x]] + d[x][y - i | p[x]]);
			if(d[x][y] < INF) q.push(mp(x, y)), in[x][y] = true;
		}
		spfa();
	}
	for(int i = 0; i < o; i++) {
		for(int j = 1; j <= n; j++)
			dp[i] = min(dp[i], d[j][i]);
	}
	for(int i = 0; i < o; i++)
		if(check(i))
			for(int j = (i - 1) & i; j; j = (j - 1) & i)
				if(check(j))
					dp[i] = min(dp[i], dp[i - j] + dp[j]);
	if(dp[o-1] == INF) printf("No solution\n");
	else printf("%d\n", dp[o-1]);
}

int main()
{
	int _;
	while(scanf("%d", &_)!=EOF) {
		while(_--) {
			init();
			read();
			work();
		}
	}
	

	return 0;
}


你可能感兴趣的:(hdoj)