USACO Cowtour

/*
	ID: 13917981
	PROG: cowtour
	LANG: C++
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <ctime>
#include <vector>
#include <list>
#include <deque>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <algorithm>
#include <cmath>
#define REP(i,n) for(int i=0;i<(n);i++)
#define REP1(i,n) for(int i=1;i<=(n);i++)
#define FOR(i,a,b) for(int i=(a);i<=(b);i++)
#define CLR(x,n) memset(x,n,sizeof(x))
#define PN printf("\n")
#define read(x) scanf("%d",&x)
#define read2(x,y) scanf("%d%d",&x,&y)
#define read3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define write(x) printf("%d",x)
#define write1(x) printf("%d ",x)
#define writeln(x) printf("%d\n",x)
#define write2(x,y) printf("%d %d",x,y)
#define writeln2(x,y) printf("%d %d\n",x,y)
#define write3(x,y,z) printf("%d %d %d",x,y,z)
#define writeln3(x,y,z) printf("%d %d %d\n",x,y,z)
#define INF 1<<20
#define delta 1e-5
/*
先写暴力提交过了4个点
然后发现思路
其实一次floyd就够了
直径要么是某个片区的最长路要么跨越2个片区
某个片区的最长路一次floyd即可
2个片区的最长路必然经过加上去的那条路
以这条路的两个端点分别计算单源最短路(这个是floyd的产物,所以不用算) 
*/ 
using namespace std;

void setio(string name)
{
     string in_f=name+".in";
     string out_f=name+".out";
     freopen(in_f.c_str(),"r",stdin);
     freopen(out_f.c_str(),"w",stdout);
}
int n,x[160],y[160],p[160];
double g[160][160],d[160][160],dis[160][160],ans,d1,maxl[160];
int find1(int x){
	return p[x]==x?x:p[x]=find1(p[x]);
}
void union1(int a,int b){
	p[ find1(a) ]=find1(b);
} 
char get1(){
	char c;
	do c=getchar();while (c>'9'||c<'0');
	return c;
}
void cdis(){
	REP(i,n)
	REP(j,n)
	dis[i][j]=sqrt( (double)( ( x[i]-x[j] )*( x[i]-x[j] )+( y[i]-y[j] )*(y[i]-y[j]) ) );
}
void floyd1(){
	double min1=0;
	REP(i,n)REP(j,n)d[i][j]=i==j?0:g[i][j];
	REP(k,n)REP(i,n)REP(j,n)
	d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
	REP(i,n)REP(j,n)if ( fabs( d[i][j]-(double)(INF)) >delta )min1=max(min1,d[i][j]); 
	//REP(i,n){	REP(j,n)printf("%.6f ",d[i][j]);PN;}
	d1=min1;
	
}
void init(){
	read(n);
	REP(i,n)read2(x[i],y[i]);
	REP(i,n)p[i]=i;
	cdis();
	REP(i,n)REP(j,n)g[i][j]=INF;
	REP(i,n)REP(j,n){
		char c=get1();
		if (c=='1') {
			union1(i,j);
			g[i][j]=dis[i][j];g[j][i]=dis[j][i];
		}
	}
	floyd1();
	//REP(i,n){	REP(j,n)printf("%.6f ",g[i][j]); PN;}
	//REP(i,n){	REP(j,n)printf("%.6f ",dis[i][j]); PN;}
	//REP(i,n)writeln3(x[i],y[i],p[i]);
}

void solve(){
	ans=INF;
	REP(i,n){
		maxl[i]=0;
		REP(j,n)if ( fabs( d[i][j]-(double)(INF) ) >delta)
		maxl[i]=max(maxl[i],d[i][j]);
	}
	REP(i,n)
	FOR(j,i+1,n-1)if (find1(i)!=find1(j)){
		//writeln2(i,j);PN;
		ans=min(ans,max( d1, dis[i][j]+maxl[i]+maxl[j] ) );
		
	}
	printf("%.6f\n",ans);
}
int main()
{
    setio("cowtour");
    init();
    solve();
    //printf("%f\n",(double)clock()/CLOCKS_PER_SEC);
    //system("pause");
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值