原题地址 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;
}