题意
给出完全图,两点间边权
w
u
→
v
=
a
u
+
a
v
+
p
∣
u
−
v
∣
w_{u\to v}=a_u+a_v+p|u-v|
wu→v=au+av+p∣u−v∣
求最小生成树大小
60pts
prim暴搞
不要装x写static
#define FILE(x) freopen(x".in","r",stdin);freopen(x".out","w",stdout);
#include<bits/stdc++.h>
using namespace std;
#define in Read()
#define re register
#define int long long
int in{
int i=0,f=1;char ch=0;
while(!isdigit(ch)&&ch!='-') ch=getchar();
if(ch=='-') ch=getchar(),f=-1;
while(isdigit(ch)) i=(i<<3)+(i<<1)+ch-48,ch=getchar();
return i*f;
}
const int N=1e5+5,inf=1e18;
int n,p,a[N],d[N];
bool vis[N];
signed main(){
// FILE("graph");
n=in,p=in;
for(re int i=1;i<=n;++i) a[i]=in,d[i]=inf;
vis[1]=true;d[1]=0;
for(re int i=2;i<=n;++i) d[i]=min(d[i],a[1]+a[i]+p*abs(i-1));
for(re int i=1;i<n;++i){
int u=0;
for(re int j=1;j<=n;++j)
if(!vis[j]&&(u==0||d[u]>d[j]))
u=j;
vis[u]=true;
for(re int v=1;v<=n;++v)
if(!vis[v]&&u!=v) d[v]=min(d[v],a[u]+a[v]+p*abs(u-v));
}
int ans=0;
for(re int i=1;i<=n;++i) ans+=d[i];
printf("%lld\n",ans);
return 0;
}
正解
必须要Boruvka算法
可惜我只会思想
合并连通块
正扫+倒扫,即把
a
u
+
a
v
+
p
∣
u
−
v
∣
a_u+a_v+p|u-v|
au+av+p∣u−v∣拆成
a
u
±
p
u
a_u\pm pu
au±pu与
a
u
∓
p
v
a_u\mp pv
au∓pv
看选哪个
维护最小合并值与次小合并值
#include<bits/stdc++.h>
using namespace std;
#define in Read()
int in{
int i=0,f=1;char ch=0;
while(!isdigit(ch)&&ch!='-') ch=getchar();
if(ch=='-') ch=getchar(),f=-1;
while(isdigit(ch))
i=(i<<3)+(i<<1)+ch-48,ch=getchar();
return i*f;
}
typedef long long ll;
const int N=1e5+5;
const ll inf=1e18;
int n,fa[N];
ll del[N],ans,p,v[N];
int cnt;
struct anti{
int st;
ll wei;
}dp1,dp2,tmp[N],grp[N];
int get(int x){return x==fa[x]?x:fa[x]=get(fa[x]);}
void update(int st,ll wei){
if (dp1.wei>wei){
if(dp1.st!=st)
dp2=dp1;
dp1.wei=wei;
dp1.st =st;
}else if(dp2.wei>wei&&st!=dp1.st){
dp2.wei=wei;
dp2.st =st;
}
return;
}
int main(){
n=in,p=in;
for(int i=1;i<=n;++i)
v[i]=in,fa[i]=i;
for(int i=1;i<=n;++i)
del[i]=del[i-1]+p;
cnt=n;
while(cnt!=1){
dp1.wei=dp2.wei=inf;
for(int i=1;i<=n;++i)
tmp[i].wei=grp[i].wei=inf;
for(int i=1;i<=n;++i){
if(dp1.st!=fa[i]){
if (tmp[i].wei>dp1.wei+del[i]){
tmp[i].wei=dp1.wei+del[i];
tmp[i].st =dp1.st;
}
}else{
if (tmp[i].wei>dp2.wei+del[i]){
tmp[i].wei=dp2.wei+del[i];
tmp[i].st =dp2.st;
}
}
update(fa[i],v[i]-del[i]);
}
dp1.wei=dp2.wei=inf;
for(int i=n;i>=1;--i){
if(dp1.st!=fa[i]){
if (tmp[i].wei>dp1.wei-del[i]){
tmp[i].wei=dp1.wei-del[i];
tmp[i].st =dp1.st;
}
}else{
if (tmp[i].wei>dp2.wei-del[i]){
tmp[i].wei=dp2.wei-del[i];
tmp[i].st =dp2.st;
}
}
update(fa[i],v[i]+del[i]);
}
for(int i=1;i<=n;++i){
// printf("%d %lld\n",tmp[i].st,tmp[i].wei);
tmp[i].wei+=v[i];
if (grp[fa[i]].wei>tmp[i].wei)
grp[fa[i]] =tmp[i];
}
// system("pause");
// puts("qwq");
for(int i=1;i<=n;++i){
int a=get(i),
b=get(grp[a].st);
if(a!=b){
--cnt;
fa[a]=b;
ans+=grp[a].wei;
}
}
for(int i=1;i<=n;++i)
fa[i]=get(fa[i]);
}
printf("%lld\n",ans);
return 0;
}
/*
6 14
25 171 7 1 17 162
*/