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

include

include

include

include

include

include

include

include

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 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 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].Xpt[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(u0&&v0){
st[0]=i; continue;
}
if(un+1&&vn+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(ij) 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&&tjn+1){
tmp=max(tmp,ww1.0/4);
}else if(ti
0){
tmp=max(tmp,pt[tj].Xpt[tj].X1.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_i0&&ans_jn+1){
ans_x=w1.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  阅读(290)  评论(0)    收藏  举报