正解:状压$dp$
解题报告:
$8102$年的时候就想搞这题了,,,$9102$了$gql$终于开始做这题了$kk$
发现有意义的状态只有当前选的点集和深度,所以设$f_{i,j}$表示当前深度为$i$,选了的点集状态为$j$.
然后转移就$f_{i,S}=min(f_{i-1,S_0}+cost)$,其中$S_0$为$S$的子集,$cost$为$S xor S_0$中的所有点和$S_0$的连边乘以$i$.
正确性显然?然后说下就,这里是并没有限制一定是和第$i-1$层的点连边的嘛,这样看起来有锅但其实是没问题的$QwQ$.就因为这样显然只会导致更劣,但这个情况一定会在其他转移中被正确转移到,所以是没影响的(,,,我$484$讲得还是不太清楚,,,$umm$如果没懂直接在评论区问趴$kk$.
然后就做完了$QwQQQQQ.$
#include<bits/stdc++.h> using namespace std; #define il inline #define int long long #define gc getchar() #define ri register int #define rb register bool #define rc register char #define lowbit(x) (x&(-x)) #define rp(i,x,y) for(ri i=x;i<=y;++i) #define my(i,x,y) for(ri i=x;i>=y;--i) const int N=15,inf=1e9; int n,m,dis[N][N],f[N][1<<N],S,as,lg[1<<N]; il int read() { ri x=0;rb y=1;rc ch=gc; while(ch!='-' && (ch<'0' || ch>'9'))ch=gc; if(ch=='-')ch=gc,y=0; while(ch>='0' && ch<='9')x=(x<<1)+(x<<3)+(ch^'0'),ch=gc; return y?x:-x; } il int cal(ri x,ri y) { ri ret=0; while(x) { ri nw=lg[lowbit(x)],tmp=y,t=inf;x-=lowbit(x); while(tmp)t=min(t,dis[nw][lg[lowbit(tmp)]]),tmp-=lowbit(tmp);;ret+=t; } return ret; } signed main() { freopen("3959.in","r",stdin);freopen("3959.out","w",stdout); n=read();m=read();memset(dis,63,sizeof(dis)); rp(i,1,m){ri x=read()-1,y=read()-1,z=read();dis[x][y]=dis[y][x]=min(dis[x][y],z);} memset(f,63,sizeof(f));rp(i,0,n-1)f[0][1<<i]=0,lg[1<<i]=i;S=(1<<n)-1; rp(i,1,S){ri j=(i-1)&i;while(j){ri k=i^j,d=cal(k,j);rp(p,1,n-1)f[p][i]=min(f[p][i],f[p-1][j]+d*p);j=(j-1)&i;}} as=f[0][0];rp(i,0,n-1)as=min(as,f[i][S]);printf("%lld ",as); return 0; }