NKOJ 4273 star way to heaven【最小生成树卡Kruskal必须Prim】

在这里插入图片描述

注意到我们可以转换成图求最小生成树,但是边数太多,用Kruskal只能80分,必须用Prim。

但是完全不会写Prim,改悔!

还是要多注意不同算法的效率差异。

#include <bits/stdc++.h>
#define ll long long
using namespace std;

const ll N=2e5+5;
const ll Inf=1e18;

ll x[N],y[N];
ll n,m,k,ans,dis[N],vis[N];
ll cnt,to[N],edge[N],from[N],nxt[N],head[N];

void ins(ll x,ll y,ll z) {
	to[++cnt]=y;nxt[cnt]=head[x];edge[cnt]=z;head[x]=cnt;
}

ll calc(ll a,ll b) {
    if (a>k||b>k) return (y[a]-y[b])*(y[a]-y[b]);
    else return (x[a]-x[b])*(x[a]-x[b])+(y[a]-y[b])*(y[a]-y[b]);
}

void prim() {
	for(ll i=1;i<=k+2;i++) dis[i]=Inf;dis[k+1]=0;
	
	for(ll i=1;i<=k+2;i++) {
		ll x=0,mn=Inf;
		for(ll j=1;j<=k+2;j++) if(!vis[j]&&dis[j]<mn) mn=dis[j],x=j;
		
		vis[x]=1;
		
		if(from[x]) ins(x,from[x],dis[x]),ins(from[x],x,dis[x]);
		
		for(ll j=1;j<=k+2;j++) if(!vis[j]&&calc(x,j)<dis[j]) dis[j]=calc(x,j),from[j]=x;
	}
}

void dfs(ll x,ll fa,ll mx) {
    if(x==k+2) ans=mx;
    
    for(ll i=head[x];i;i=nxt[i]) {
    	ll y=to[i],z=edge[i];
    	if(y!=fa) dfs(y,x,max(mx,z));
    }
}

int main() {
    scanf("%d%d%d",&n,&m,&k);
    
    for(ll i=1;i<=k;i++) scanf("%d%d",&x[i],&y[i]);
    
    y[k+1]=0,y[k+2]=m;
    
    prim();
    
    dfs(k+1,0,0);
    
    printf("%.8lf\n",sqrt(ans)/2.0);
    
    return 0;
} 

猜你喜欢

转载自blog.csdn.net/yanzhenhuai/article/details/83514021
way