P3959 宝藏

原题地址 https://www.luogu.org/problemnew/show/P3959

关于随机化:

上帝不掷筛子。 ——爱因斯坦

不要指挥上帝怎么做。 ——波尔


这与自然选择类似,即有概率发生基因突变:

物竞天择,适者生存 ——Darwin

主体思路 :最小生成树,随机化

首先打一个最小生成树板子,枚举起点,得到45pts
然后根据实际情况确定循环次数,每次扩展新边时,有概率不选择最短边,而要选择较长边
#include <iostream>
#include <fstream>
#include <cstdio>
#include <stdlib.h>
using namespace std;
int m,n,x,y,l,en=0;
const int maxn=13;
const int maxm=2001;
const int maxt=1000;
const int INF=2147483640;
long long int ans=0,anse=INF;
int v2[maxn],f[maxn],a[maxn][maxn];
bool v1[maxn];
int qread(){
    int x=0;char ch=getchar();
    while(ch>'9'||ch<'0')ch=getchar();
    while(ch<='9'&&ch>='0'){
        x=x*10+ch-'0';
        ch=getchar();
    }
    return x;
}
void csh(){
    for(int i=1;i<=n;i++){
    v1[i]=true;
    v2[i]=INF;
    f[i]=0;
      }
}
int main(){
   // freopen("3959_15.txt","r",stdin);
    //freopen("3959.out","w",stdout);
     n=qread();m=qread();
     for(int i=1;i<=n;i++){
       f[i]=0;
        for(int j=1;j<=n;j++){
            a[i][j]=a[j][i]=INF;
        }
     }
     for(int i=1;i<=m;i++){
        x=qread();y=qread();l=qread();
        a[x][y]=a[y][x]=min(a[x][y],l);
      }
      //for(int i=1;i<=m*2;i++)cout<<i<<' '<<e[i].fr<<' '<<e[i].to<<' '<<e[i].len<<' '<<e[i].nxt<<endl;
      srand(551);
       for(int TIME=1;TIME<=10000;TIME++){

        bool can=true;
        for(int st=1;st<=n;st++){
           can=true;
            ans=0;
            csh();
                 v2[st]=0;
                  int time=0;
                   while(time<n){
                    time++;
                    int t=-1,minn=INF;
                    bool hf=true;

                    for(int i=1;i<=n;i++){
                        if(v1[i]&&v2[i]<minn){
                           if(rand()%TIME>2000){//#12把1改为10 +500
                            t=i; minn=v2[i];
                           }
                            //  else cout<<TIME<<endl;
                        } 
                       }
                       if(t<0){
                        can=false;
                        continue;
                       }
                     //  cout<<t<<' ';
                       if(t>0)v1[t]=false;
                       //cout<<t<<' '<<f[t]<<endl;
                       ans+=f[t]*v2[t];
                     for(int i=1;i<=n;i++){
                        if(v1[i]&&(a[t][i]<v2[i])){
                            v2[i]=a[t][i];
                            f[i]=f[t]+1;
                         }
                     }
                   }

           //cout<<endl;
         //  if(ans!=anse)cout<<TIME<<' '<<ans<<endl;
           if(can)anse=min(ans,anse);
           }
            //在这里把更新anse移动括号内部 
       }


            cout<<anse<<endl;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值