标签:
给定一张带权有向图,要求从顶点0出发,经过每个结点恰好一次后再返回0,求边权和的最小值。
2<=n<=15
0<=d(i,j)<=1000
样例
5 8
0 1 3
0 3 4
1 2 5
2 0 4
2 3 5
3 4 3
4 0 7
4 1 6
dp[S][U]=min{dp[S∪{V}][V]+d(U,V)|V∉S&&d(U,V)!=INF},
d[(1<<n)-1][0]=0.
O(2^n*n^2)
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define N 16 #define INF 214748364 #define M 250 int n,m; int v[M<<1],w[M<<1],first[N],next[M<<1],en; void AddEdge(int U,int V,int W) { v[++en]=V; w[en]=W; next[en]=first[U]; first[U]=en; } int dp[(1<<N)+1][N]; int f(int S,int U) { if(dp[S][U]!=-1) return dp[S][U]; if(S==(1<<n)-1&&(!U)) return dp[S][U]=0; int res=INF; for(int i=first[U];i;i=next[i]) if(!(S>>v[i]&1)) res=min(res,f(S|(1<<v[i]),v[i])+w[i]); return dp[S][U]=res; } int main() { int x,y,z; scanf("%d%d",&n,&m); for(int i=1;i<=m;++i) { scanf("%d%d%d",&x,&y,&z); AddEdge(x,y,z); } memset(dp,-1,sizeof(dp)); printf("%d\n",f(0,0)); return 0; }
标签:
原文地址:http://www.cnblogs.com/autsky-jadek/p/4496609.html