USACO:Cow Tours解题报告

来源:互联网 发布:ubuntu root切换用户 编辑:程序博客网 时间:2024/05/22 17:33

思路:先用floodfill得到各连通区域,然后用floyd-warshall得到各连通区域中各点间的最短路径,最后枚举连接不在同一连通区域中的两点并计算新的直径。需要注意的是:通过这样连接得到的直径也许不是整个牧场中最远两个牧区的距离,因为它有可能比期中某个子连通区域的直径小,即最远距离的两个牧区可能就在连接之前的某个连通区域中,因此在最后需要和每个连通区域中的最远距离比较从而得到最终结果。

 

 

/*
ID: xpli1
PROG: cowtour
LANG: C
*/

#include <stdio.h>
#include <math.h>

#define max(a,b) (((a) > (b)) ? (a) : (b))
#define min(a,b) (((a) < (b)) ? (a) : (b))

#define IN stdin
#define OUT stdout

#define MAX_SIZE  160

unsigned short mx[MAX_SIZE][MAX_SIZE];
double dis[MAX_SIZE][MAX_SIZE];
double max_dis[MAX_SIZE];
int cx[MAX_SIZE],cy[MAX_SIZE];
int comp[MAX_SIZE];
char buf[MAX_SIZE];
double MIN;
int N;


void flood_fill(int new_comp)
{
 int num_visited,i,j;
 do{
  num_visited = 0;

  for(i=0; i<N; i++){
   if(comp[i] == -1){
    num_visited++;
    comp[i] = new_comp;
    for(j=0; j<N; j++){
     if(mx[i][j]){
      if(comp[j] == -2)
       comp[j] = -1;
     }
    }
   }
  }
 } while (num_visited);

 return;
}

void find_comp()
{
 int new_comp = 0,i;

 for(i=0; i<N; i++)
  comp[i] = -2;      // 未扩展且未访问

 for(i=0; i<N; i++){
  if(comp[i] == -2){
   new_comp++;
   comp[i] = -1;  //  扩展但未访问
   flood_fill(new_comp);
  }
 }
 return;
}

void floyd_warshall()
{
 int i,j,k;
 
 for(i=0; i<N; i++){
  for(j=0; j<N; j++){
   if(mx[i][j] || i==j) dis[i][j] = sqrt((cx[i]-cx[j])*(cx[i]-cx[j])+(cy[i]-cy[j])*(cy[i]-cy[j]));
   else dis[i][j] = 1000000;
  }
 }

 for(k=0; k<N; k++){
  for(i=0; i<N; i++){
   for(j=0; j<N; j++){
    if(comp[i] == comp[j] && comp[j] == comp[k]){
     if(dis[i][k] + dis[k][j] < dis[i][j])
      dis[i][j] = dis[i][k] + dis[k][j];
    }
   }
  }
 }

 for(i=0; i<N; i++){
  max_dis[i] = -1;
  for(j=0; j<N; j++){
   if(comp[i] == comp[j]){
    if(max_dis[i] < dis[i][j]) max_dis[i] = dis[i][j];
   }
  }
 }

 return;
}

void connect_check()
{
 int i,j;

 MIN = 1000000;

 for(i=0; i<N; i++){
  for(j=0; j<N; j++){
   if(comp[i] != comp[j]){
    if(MIN > max_dis[i] + max_dis[j] + sqrt((cx[i]-cx[j])*(cx[i]-cx[j])+(cy[i]-cy[j])*(cy[i]-cy[j])))
     MIN = max_dis[i] + max_dis[j] + sqrt((cx[i]-cx[j])*(cx[i]-cx[j])+(cy[i]-cy[j])*(cy[i]-cy[j]));
   }
  }
 }

 for(i=0; i<N; i++){
  if(MIN < max_dis[i])
   MIN = max_dis[i];
 }
 return;
}

int main(void)
{
 FILE* fin = fopen("cowtour.in","r");
 FILE* fout = fopen("cowtour.out","w");

 fscanf(IN,"%d",&N);

 int i,j;

 for(i=0; i<N; i++) 
  fscanf(IN,"%d%d/n",&cx[i],&cy[i]);

 for(i=0; i<N; i++){
  fgets(buf,sizeof(buf),IN);
  for(j=0;j<N; j++){
   mx[i][j] = buf[j] - '0';
  }
 }

 find_comp();

 floyd_warshall();

 connect_check();
 
 fprintf(OUT,"%.6lf/n",MIN);
 return 0;
}