题解 P3959 【宝藏】

caidd

2018-04-19 21:19:34

Solution

看到题解里那么多大佬用一些高级算法,蒟蒻不知什么意思,但蒟蒻有一种比较简单的随机化想法。就是复杂度可能较高。 核心想法如下, ```cpp random_shuffle(s+1,s+1+n); ``` 每次重置一次宝屋的顺序。 以便于得到顺序,统计层数,每到一个点,就选取已开通的且到该屋子最近的点 代码如下 ```cpp #include<cstdio> #include<iostream> #include<cstring> #include<algorithm> using namespace std; const int INF=0x3f3f3f3f; void read(int &x) { x=0;char a=getchar(); while(a<'0'||a>'9')a=getchar(); while(a>='0'&&a<='9')x=(x<<3)+(x<<1)+(a^48),a=getchar(); } int dis[13][13],s[13],dep[13];//s是每次要打乱的顺序队列 int main() { int n,m,x,y,z,v,mv,mp,ans=0x3f3f3f3f;scanf("%d%d",&n,&m); memset(dis,0x3f,sizeof(dis)); for(int i=1;i<=n;++i)dis[i][i]=0,s[i]=i; while(m--) { read(x);read(y);read(z); if(dis[x][y]>z) dis[x][y]=z,dis[y][x]=z; } //为保证正确性,卡住时间,多随机几次 for(int times=1;times<=100000;++times) { random_shuffle(s+1,s+1+n);v=0; memset(dep,0,sizeof(dep)); dep[s[1]]=1;//第一个屋子 for(int i=2;i<=n;++i) { int t=s[i];mv=INF;mp=0; for(int j=1;j<=n;++j) { if(!dep[j]||dis[j][t]==INF)continue; //若前一个屋子未被开发,或路径不存在,就继续 if(mv>dis[j][t]*dep[j])mv=dis[j][t]*dep[j],mp=j; }if(!mp)goto end; //偷懒用了goto,若当前点无屋子可到,则放弃此次随机。 dep[t]=dep[mp]+1;v+=mv; } ans=min(ans,v);end:; //每次取ans最小 } printf("%d",ans); return 0; } ```