思路:类似TSP问题,不过每个点可以经过不超过两次,那么就可以考虑用三进制来压缩状态,先预处理出每个数的三进制的第j位是什么,然后其他就和TSP类似的
坑点:有重边
#include<bits/stdc++.h>
using namespace std;
const int maxn = 60000;
#define inf 0x3f3f3f
int three[]={0,1,3,9,27,81,243,729,2187,6561,19683,59049};
int n,m;
int mp[12][12];
int dp[maxn][12];
int dig[maxn][12]; //3进制数i的第j位是什么
void init()
{
for(int i = 0;i<maxn;i++)
{
int t = i;
for(int j = 1;j<=10;j++)
{
dig[i][j]=t%3;
t/=3;
if(!t)break;
}
}
}
int main()
{
init();
while(scanf("%d%d",&n,&m)!=EOF)
{
memset(mp,0,sizeof(mp));
for(int i= 1;i<=m;i++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
if(mp[u][v]==0)
{
mp[u][v]=w;
mp[v][u]=w;
}
if(w<mp[u][v] && mp[u][v]!=0)
{
mp[u][v]=w;
mp[v][u]=w;
}
}
int ans = inf;
memset(dp,inf,sizeof(dp));
for(int i = 1;i<=n;i++)
dp[three[i]][i]=0;
for(int s = 1;s<three[n+1];s++)
{
int flag = 1;
for(int i = 1;i<=n;i++)
{
if(!dig[s][i])flag=0;
if(dp[s][i]==inf)continue;
for(int j = 1;j<=n;j++)
{
if(i==j)continue;
if(dig[s][j]>=2 || !mp[i][j])continue;
dp[s+three[j]][j]=min(dp[s][i]+mp[i][j],dp[s+three[j]][j]);
}
}
if(flag)
for(int i = 1;i<=n;i++)
ans = min(ans,dp[s][i]);
}
if(ans==inf)
printf("-1\n");
else
printf("%d\n",ans);
}
}