Gym - 100851F Froggy Ford kruskal

题目链接:

http://acm.hust.edu.cn/vjudge/problem/307216

Froggy Ford

Time Limit: 3000MS

题意

青蛙过河,河中有若干个石头,现在你可以加一个石头,使得青蛙从左岸跳到右岸的最大跳跃距离最小。

题解

把左岸和右岸作为两个虚节点,用kruskal的思路处理出每个点到左岸需要跳跃的最大距离st[i](最优情况下)和每个点到右岸的最大距离ed[i],然后枚举两个点,在这两个点的中点放一个石头,得到ma=max(st[i],ed[j],dis(i,j)/2),如果这个值比答案更优,就更新答案,同时记录新放的石头的坐标。

代码

#include<map>
#include<cmath>
#include<queue>
#include<vector>
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define X first
#define Y second
#define mkp make_pair
#define lson (o<<1)
#define rson ((o<<1)|1)
#define mid (l+(r-l)/2)
#define sz() size()
#define pb(v) push_back(v)
#define all(o) (o).begin(),(o).end()
#define clr(a,v) memset(a,v,sizeof(a))
#define bug(a) cout<<#a<<" = "<<a<<endl
#define rep(i,a,b) for(int i=a;i<(b);i++)

typedef long long LL;
typedef vector<int> VI;
typedef pair<int,int> PII;
typedef vector<pair<int,int> > VPII;

const int INF=0x3f3f3f3f;
const LL INFL=9e18;
const double eps=1e-8;

const int maxn=1111;

LL w,n;

pair<LL,LL> pt[maxn];

LL dis(LL x1,LL y1,LL x2,LL y2){
	return (x1-x2)*(x1-x2)+(y1-y2)*(y1-y2);
}

struct Edge{
	int u,v; 
	LL w;
	Edge(int u,int v,LL w):u(u),v(v),w(w){}
	Edge(){}
	bool operator < (const Edge& tmp) const {
		return w<tmp.w;
	}
}egs[maxn*maxn];

int tot;
int fa[maxn];
int find(int x){
	return fa[x]=fa[x]==x?x:find(fa[x]);
}

vector<int> G[maxn];
int st[maxn],ed[maxn];

void init(){
	clr(st,-1);
	clr(ed,-1);
	tot=0;
	rep(i,0,maxn) fa[i]=i;
	rep(i,0,maxn) G[i].push_back(i);
}

int main() {
	freopen("froggy.in","r",stdin);
	freopen("froggy.out","w",stdout);
	
	init();
	
	scanf("%I64d%I64d",&w,&n);
	rep(i,1,n+1) scanf("%I64d%I64d",&pt[i].X,&pt[i].Y);
	
	rep(i,1,n+1){
		egs[tot++]=Edge(0,i,pt[i].X*pt[i].X);
	}
	rep(i,1,n+1){
		egs[tot++]=Edge(i,n+1,(w-pt[i].X)*(w-pt[i].X)); 
	}
	rep(i,1,n+1){
		rep(j,i+1,n+1){
			egs[tot++]=Edge(i,j,dis(pt[i].X,pt[i].Y,pt[j].X,pt[j].Y));
		}
	}
	egs[tot++]=Edge(0,n+1,w*w);
	egs[tot++]=Edge(0,0,0);
	egs[tot++]=Edge(n+1,n+1,0);
	sort(egs,egs+tot);
	
	rep(i,0,tot){
		int u=egs[i].u,v=egs[i].v;
		if(u==0&&v==0){
			st[0]=i; continue;
		}
		if(u==n+1&&v==n+1){
			ed[n+1]=i; continue;
		}
		int pu=find(u);
		int pv=find(v);
		if(pu!=pv){
			if(find(0)==pu){
				rep(j,0,G[pv].size()){
					int tt=G[pv][j];
					st[tt]=i;
				}
			}else if(find(0)==pv){
				rep(j,0,G[pu].size()){
					int tt=G[pu][j];
					st[tt]=i;
				}
			}
			if(find(n+1)==pu){
				rep(j,0,G[pv].size()){
					int tt=G[pv][j];
					ed[tt]=i;
				}
			}else if(find(n+1)==pv){
				rep(j,0,G[pu].size()){
					int tt=G[pu][j];
					ed[tt]=i;
				}
			}
			fa[pv]=pu;
			while(G[pv].size()>0){
				G[pu].push_back(G[pv][G[pv].sz()-1]);
				G[pv].pop_back();
			}
		}
	}
	
	int ans_i=0,ans_j=0;
	double mi=9000000000000000000;
	rep(i,0,n+2){
		rep(j,0,n+2){
			if(i==j) continue;
			double tmp=max(egs[st[i]].w,egs[ed[j]].w);
			int ti=i,tj=j;
			if(ti>tj) swap(ti,tj);
			if(ti==0&&tj==n+1){
				tmp=max(tmp,w*w*1.0/4);
			}else if(ti==0){
				tmp=max(tmp,pt[tj].X*pt[tj].X*1.0/4);
			}else if(tj==n+1){
				tmp=max(tmp,(w-pt[ti].X)*(w-pt[ti].X)*1.0/4);
			}else{
				tmp=max(tmp,dis(pt[i].X,pt[i].Y,pt[j].X,pt[j].Y)*1.0/4);
			}
			if(tmp<mi){
				mi=tmp;
				ans_i=i; ans_j=j;
			}
		}
	}
	
	double ans_x=0,ans_y=0;
	if(ans_i>ans_j) swap(ans_i,ans_j);
	if(ans_i==0&&ans_j==n+1){
		ans_x=w*1.0/2;
		ans_y=0;
	}else if(ans_i==0){
		ans_x=pt[ans_j].X*1.0/2;
		ans_y=pt[ans_j].Y;
	}else if(ans_j==n+1){
		ans_x=(w+pt[ans_i].X)*1.0/2;
		ans_y=pt[ans_i].Y;
	}else{
		ans_x=(pt[ans_i].X+pt[ans_j].X)*1.0/2;
		ans_y=(pt[ans_i].Y+pt[ans_j].Y)*1.0/2; 
	}
	
	printf("%.3lf %.3lf\n",ans_x,ans_y);
	return 0;
}
posted @ 2016-08-14 00:52  fenicnn  阅读(260)  评论(0编辑  收藏  举报