At the beginning, most people think that this is a minimum spanning tree problem, which can be solved by prim. However, in fact, due to the limitation of multiple and depth, this algorithm is not necessarily correct. So what should I do? We just need to make a judgment before finding the smallest point, and use random numbers to get modulus, so as to ensure that there is a very small probability to get the next small, smaller probability to get the next small Point, this process repeats 1000 times (almost), basically can pass.
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #include<cstdlib> #include<iomanip> #include<queue> #include<cmath> #include<ctime> #define INF 0x3f3f3f3f using namespace std; const int maxn=20; const int maxm=1010; int e[maxn][maxn]; int dis[maxn],depth[maxn]; bool b[maxn],inq[maxn]; struct H { int id; }; int n,m,ans; priority_queue<H> q; queue<H> p; bool operator < (const H &a,const H &b) { return dis[a.id]>dis[b.id]; } int f(int x) { memset(dis,INF,sizeof(dis)); memset(b,false,sizeof(b)); memset(inq,false,sizeof(inq)); memset(depth,0,sizeof(depth)); while(!q.empty()) q.pop(); while(!p.empty()) p.pop(); dis[x]=0; depth[x]=1; q.push((H){x}); inq[x]=true; int tot=0; for(int i=1;i<=n;i++) { H now=q.top(); q.pop(); while(!q.empty()&&(rand()%10==0)) { p.push(now); now=q.top(); q.pop(); } while(!p.empty()) { q.push(p.front()); p.pop(); } int tmp=now.id; b[tmp]=true; tot+=dis[tmp]; if(tot>ans) return INF; for(int j=1;j<=n;j++) { if(!b[j]&&e[tmp][j]!=INF&&dis[j]>depth[tmp]*e[tmp][j]) { dis[j]=depth[tmp]*e[tmp][j]; depth[j]=depth[tmp]+1; if(!inq[j]) { inq[j]=true; q.push((H){j}); } } } } return tot; } int main() { scanf("%d %d",&n,&m); memset(e,INF,sizeof(e)); for(int i=1;i<=m;i++) { int x,y,z; scanf("%d %d %d",&x,&y,&z); if(z<e[x][y]) { e[x][y]=z; e[y][x]=z; } } ans=INF; srand(1919); for(int i=1;i<=1000;i++) { for(int j=1;j<=n;j++) { ans=min(ans,f(j)); } } printf("%d",ans); return 0; }