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



 


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章