写的爆搜。结果RE 10pts.看不出来哪里会RE,求调。
#include <bits/stdc++.h>
using namespace std;
const int inf=1917483645;
const int maxn=20;
int vis[maxn],len[maxn],deg[maxn];
//已访问的点,路径长度,出度数
int w[maxn][maxn],p[maxn][maxn];
int now;
//p[i][j]:点i第j条边能到的点(按边权排序后)
int n,m,ans=inf,tot,cnt,tmp;//tmp理论最优值,有点像A*了
inline bool cmp(int a,int b){return w[now][a]<w[now][b];}//排序
#define itn int
#define re return
inline void dfs(int num,int cur)//当前开发到哪个店,剪枝参数
{
for(int i=num;i<=cnt;i++)//枚举通过那个已访问的点转移
{
if(tot+tmp*len[vis[i]]>ans)return;//剪枝:最优性
for(int j=cur;j<=deg[vis[i]];j++)//扩展到哪
{
if(!len[p[vis[i]][j]]) //没有被访问
{
++cnt;
vis[cnt]=p[vis[i]][j];//新建节点
tmp-=w[vis[tot]][p[vis[tot]][1]];
tot+=w[vis[i]][vis[cnt]]*len[vis[i]];//累加
len[vis[cnt]]=len[vis[i]]+1;
dfs(i,j+1);
tot-=w[vis[i]][vis[cnt]]*len[vis[i]];
len[vis[cnt]]=0;
tmp+=w[vis[cnt]][p[vis[cnt]][1]];
cnt--;//回溯
}
}
cur=1;//改回来
}
if(cnt==n)//终点
{
if(tot<ans)ans=tot;
return;
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)w[i][j]=inf;
}
for(int i=1;i<=m;i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
if(w[x][y]>=z)
{
if(w[x][y]==inf)
{
p[x][++deg[x]]=y, p[y][++deg[y]]=x;
}
w[x][y]=w[y][x]=z;
}
}
for(int i=1;i<=n;i++)
{
now=i;
sort(p[i]+1,p[i]+deg[i]+1,cmp);//排序
tmp+=w[i][p[i][1]];//开始全部加上
}
for(int i=1;i<=n;i++)
{
tot=0;cnt=1;
vis[1]=i;//第一个
tmp-=w[i][p[i][1]];//减掉
len[i]=1;
dfs(1,1);
len[i]=0;
tmp+=w[i][p[i][1]];
vis[1]=0;
}
printf("%d\n",ans);
return 0;
}