解题思路:听说状压dp有后效性,然后被Hack了。
于是用随机化大法,每次random_shuffle一个加入点的顺序,然后贪心地插入点。如此多算几次就能找到最优解(我不会证明它为什么可能找到最优解)。
C++ Code:
#include<bits/stdc++.h>
int n,m,e[13][13],p[13],d[13];
inline int readint(){
int c=getchar(),d=0;
for(;!isdigit(c);c=getchar());
for(;isdigit(c);c=getchar())
d=(d<<3)+(d<<1)+(c^'0');
return d;
}
int main(){
memset(e,0x3f,sizeof e);
n=readint(),m=readint();
for(int i=1;i<=n;++i)p[i]=i;
while(m--){
int x=readint(),y=readint(),t=readint();
if(e[x][y]>t)e[x][y]=e[y][x]=t;
}
int ans=0x3f3f3f3f;
for(int T=1,sm;T<=100000;++T){
std::random_shuffle(p+1,p+n+1);
memset(d,0,sizeof d);
sm=0;
d[p[1]]=1;
for(int i=2;i<=n;++i){
int s=0x3f3f3f3f;
for(int j=1;j<i;++j)
if(e[p[i]][p[j]]<0x3f3f3f3f&&d[p[j]]*e[p[i]][p[j]]<s){
s=d[p[j]]*e[p[i]][p[j]],d[p[i]]=d[p[j]]+1;
}
if(s==0x3f3f3f3f){
sm=s;break;
}else sm+=s;
}
if(sm<ans)ans=sm;
}
printf("%d\n",ans);
return 0;
}