记录编号 51626 评测结果 AAAAAAAAA
题目名称 [USACO 2.4.3]牛的旅行 最终得分 100
用户昵称 Gravatarcstdio 是否通过 通过
代码语言 C++ 运行时间 0.024 s
提交时间 2012-12-27 20:29:30 内存使用 0.52 MiB
显示代码纯文本
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<cstdlib>
#include<iomanip>
using namespace std;
const int SIZE=151;
const double INF=0xffffff;
class point{
	public:
	double x;
	double y;
}ran[SIZE];//每点坐标
int n,sum;
int area[SIZE]={0};//每点所属牧场
double leng[SIZE][SIZE]={0},longest[SIZE]={0},dia[SIZE]={0};//两点距离,每点到所属牧场中最远点的距离,牧场直径
//需先在leng中存入邻接矩阵,其余填充为INF,顶点下标为0~n-1
bool con[SIZE][SIZE]={0};//两点是否相邻
double ans=INF;
double ldis(int a,int b){//两点间直线距离
	double xd=ran[a].x-ran[b].x,yd=ran[a].y-ran[b].y;
	return sqrt(xd*xd+yd*yd);
}
void floyd(void){//都懂吧
	int i,j,k;
	for(k=0;k<n;k++){
		for(i=0;i<n;i++){
			if(area[i]!=area[k]||leng[i][k]==INF) continue;
			for(j=0;j<n;j++){
				if(area[k]!=area[j]||leng[k][j]==INF) continue;
				if(leng[i][k]+leng[k][j]<leng[i][j]) leng[i][j]=leng[i][k]+leng[k][j];
			}
		}
	}
}
void BFS_point(int x,int p){//搜x所在联通块,牧场号为p
	queue<int> s;
	s.push(x),area[x]=p;
	int i,temp;
	while(!s.empty()){
		temp=s.front(),s.pop();
		for(i=0;i<n;i++){
			if(i!=temp&&con[temp][i]&&area[i]==0) s.push(i),area[i]=p;
		}
	}
}
void BFS(void){//搜连通性
	int i,p=1;
	for(i=0;i<n;i++){
		if(area[i]==0) BFS_point(i,p++);
	}
	sum=p-1;
}
void diameter(void){//求每个牧场的直径
	int i,j,k;
	double amax,pmax;//牧场/当前点的最远距离
	for(i=1;i<=sum;i++){
		amax=0;
		for(j=0;j<n;j++){
			pmax=0;
			if(area[j]!=i) continue;
			for(k=0;k<n;k++){
				if(j==k||area[k]!=i) continue;
				if(leng[j][k]!=INF&&leng[j][k]>pmax) pmax=leng[j][k];
			}
			if(pmax>amax) amax=pmax;
			longest[j]=pmax;
		}
		dia[i]=amax;
	}
}
void add(void){//枚举添加道路后的情况
	int i,j;
	double nowdis,max;
	for(i=0;i<n;i++){
		for(j=0;j<n;j++){
			if(area[i]==area[j]) continue;
			nowdis=ldis(i,j);
			max=nowdis+longest[i]+longest[j];
			if(dia[area[i]]>max) max=dia[area[i]];
			if(dia[area[j]]>max) max=dia[area[j]];
			if(max<ans) ans=max;
		}
	}
}
void input(void){
	int i,j,x,y;
	char s[200]={0};
	/*就尼玛为了个\n啊!!!!!尼玛getchar怒跪啊!!!!尼玛提了26遍才幡然悔悟用数组啊!!!!!!!!
	尼玛linux的行输入得有多坑爹啊!!!!!!!!!!!!!!!!!!!!!*/
	//那啥,数组就数组吧......我是在没劲改成string了......
	scanf("%d",&n);
	for(i=0;i<n;i++) scanf("%d%d",&x,&y),ran[i].x=(double)x,ran[i].y=(double)y;
	for(i=0;i<n;i++){
		cin>>s;
		for(j=0;j<n;j++){
			con[i][j]=(s[j]=='1')?1:0;
			if(i==j){
				con[i][j]=1,leng[i][j]=0;
			}
			else{
				if(!con[i][j]) leng[i][j]=INF;
				else leng[i][j]=ldis(i,j);
			}
		}
	}
}
int main(){
	freopen("cowtour.in","r",stdin);
	freopen("cowtour.out","w",stdout);
	input();
	BFS();
	floyd();
	diameter();
	add();
	cout<<setiosflags(ios::fixed)<<setprecision(6)<<ans<<endl;
	return 0;
}