Minimal Steiner Tree

Minimal Steiner Tree 生成树问题。

定义:G(V,E),A是V的一个子集,求至少包含A中所有点的最小子树。

用动态规划解决。

 

推荐两道题:

(1) poj 3123

(2) Garden

 

//Minimal Steiner Tree
//G(V,E),A是V的一个子集,求至少包含A中所有点的最小子树
//时间复杂度 O(V^3+V*2^A*(2^A+V))
//INIT: d[][]距离矩阵; id[]置为集合A中点的标号;
//CALL: steiner(int n, int a);

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <string>
#include <cmath>
#include <vector>
using namespace std;

const int inf = 2147483647;
const int N = 205; //总顶点数
const int A = 7 ;  //要包含的顶点数
int id[A];         //包含顶点的序号
int d[N][N];       //距离矩阵
int dp[1<<A][N];  //dp[i][j]表示点j到联通的集合i的最短距离

//返回最小值
int Steiner(int n,int a)
{
	int top = 1<<a;
	for(int k=0;k<n;k++)      //vertex 0---n-1
		for(int i=0;i<n;i++)
			for(int j=0;j<n;j++)
				if(d[i][j]>d[i][k]+d[k][j])
					d[i][j]=d[i][k]+d[k][j];

	for(int i=0;i<top;i++)
		for(int j=0;j<n;j++)
			dp[i][j]=inf;

	for(int i=0;i<a;i++)
	{
		for(int j=0;j<n;j++)
			dp[1<<i][j]=d[id[i]][j];
	}
	for(int i=1;i<top;i++)
	{
		if(i&(i-1)==0)
			continue;
		for(int k=0;k<n;k++)   //init
		{
			for(int j=1;j<i;j++)
			{
				if((i|j)==i && dp[i][k]>dp[j][k]+dp[i-j][k])
					dp[i][k]=dp[j][k]+dp[i-j][k];
			}
		}

		for(int j=0;j<n;j++)  //update
		{
			for(int k=0;k<n;k++)
			{
				if(dp[i][j]>dp[i][k]+d[k][j])
					dp[i][j]=dp[i][k]+d[k][j];
			}
		}
	}

	int ans = inf;
	for(int i=0;i<n;i++)
	{
		if(ans > dp[top-1][i])
			ans=dp[top-1][i];
	}
	return ans;
}



 


 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值