Description
对于给定的加权有向图G(V,E),查找满足以下条件的最短路径的距离:
1、这条路径是一个环,即这条路径的起点和终点都是同一个点。
2、每个顶点只能访问一次。
Input
第一行为
n
,
m
n,m
n,m,分别为点数,边数。
之后m行格式为,
u
i
,
v
i
,
w
i
u_i,v_i,w_i
ui,vi,wi,表示一条从
u
i
u_i
ui到
v
i
v_i
vi长度为
w
i
w_i
wi的边
Output
满足上述条件的最短路径,若不存在,则输出-1 。
Sample Input
4 6
0 1
2 1
2 3
1 3
9 2
0 1
2 3
6 3
2 4
Sample Output
16
分析
我们不难得出这道题的dp方程为
d
p
[
S
]
[
v
]
=
m
i
n
{
d
p
[
S
∩
{
u
}
]
[
u
]
+
e
[
v
]
[
u
]
∣
u
∉
S
}
dp[S][v] = min\{dp[S\cap\{u\}][u]+e[v][u]|u\notin S\}
dp[S][v]=min{dp[S∩{u}][u]+e[v][u]∣u∈/S}
剩下需要考虑的地方就是表示S这个集合,由于此题
V
V
V较小,所以想到用二进制优化
标程
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define maxn 16
using namespace std;
int ans[1<<maxn][maxn];
int n,m;
int e[maxn][maxn];
int solve(int S,int v)
{
if(ans[S][v] >= 0)
return ans[S][v];
if(S == (1<<n)-1 && v == 0)
return ans[S][v] = 0;
int now = 0x7f7f7f7f;
for(int i = 0;i < n;i++)
{
if(e[v][i] != 0x7f7f7f7f && !((S >> i) & 1))
now = min(now,solve(S | (1 << i),i) + e[v][i]);
}
return ans[S][v] = now;
}
int main()
{
freopen("tsp.in","r",stdin);
freopen("tsp.out","w",stdout);
memset(ans,-1,sizeof(ans));
memset(e,0x7f,sizeof(e));
cin>>n>>m;
while(m--)
{
int x,y,z;
cin>>x>>y>>z;
e[x][y] = z;
}
int kkk = solve(0,0);
if(kkk == 0x7f7f7f7f)
cout<<-1;
else
cout<<kkk;
return 0;
}