和正常的没什么不同,就是一个点可以到两次,所以就用三进制来压
并且,TSP的问题的状态表示都是dp【i】【k】,经过的点的集合表示为i,且现在走到k时的最短距离
//同时,注意初始化最大值之类的,例如表示距离的,如果没有说就是最大值
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
int n,a[12][12],m,f[531445][12];
int main()
{
while (scanf("%d%d",&n,&m)!=EOF)
{
memset(a,0x3f3f3f3f,sizeof(a));
int x,y,z;
while (m--)
{
scanf("%d%d%d",&x,&y,&z);
if (a[x][y]==0x3f3f3f3f)a[x][y]=a[y][x]=z;
else a[x][y]=a[y][x]=min(a[x][y],z);
}
memset(f,0x3f3f3f3f,sizeof(f));
int p=1;
for (int i=1;i<=n;i++)
{
f[p][i]=0;
p*=3;
}
p--;
for (int pp=1;pp<=p;pp++)
{
int b[20]={0},l=pp;
while (l) b[++b[0]]=l%3,l/=3;
for (int i=1;i<=n;i++) if (b[i])
{
int c[20];
memcpy(c,b,sizeof(c));
c[i]--;
int k=0;
for (int j=n;j>0;j--) k=k*3+c[j];
for (int j=1;j<=n;j++) if (i!=j)
f[pp][i]=min(f[pp][i],f[k][j]+a[j][i]);
}
}
int ans=0x3f3f3f3f;
for (int i=1;i<=p;i++)
{
int b[20]={0},l=i,j;
while (l) b[++b[0]]=l%3,l/=3;
for (j=1;j<=n;j++) if (b[j]==0) break;
if (j<=n) continue;
for (j=1;j<=n;j++) ans=min(ans,f[i][j]);
}
if (ans!=0x3f3f3f3f) printf("%d\n",ans);else printf("-1\n");
}
return 0;
}