洛谷P1522 [USACO2.4]牛的旅行 Cow Tours

题目要求的是两个牧场的最小直径,数据给出不只是两个独立牧场而是至少两个

所以我们要去暴力枚举每个不属于同一牧场的直径的最小值

这里需要注意的是两个牧场连起来的直径不一定是连线后 i所在的最短路+j所在的最短路+dis(i,j);

例如

 

 

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const double inf=1e15;
 4 const int N=200;
 5 int x[N],y[N],field[N];
 6 double dis[N][N],dismx[N],field_max[N];
 7 int n;
 8 double getdis(int i,int j)
 9 {
10     return sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
11 }
12 void dfs(int x,int id)
13 {
14     field[x]=id;
15     for(int i=1;i<=n;i++)
16     {
17         if(!field[i]&&dis[x][i]!=inf)
18         dfs(i,id);
19     }
20 }
21 void floyd()
22 {
23     for(int k=1;k<=n;k++)
24     for(int i=1;i<=n;i++)
25     for(int j=1;j<=n;j++)
26     dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
27 }
28 int main()
29 {
30 
31     scanf("%d",&n);
32     for(int i=1;i<=n;i++)
33     scanf("%d%d",&x[i],&y[i]);    
34      
35     char ch[n+1];
36     for(int i=1;i<=n;i++)
37     {
38         scanf("%s",ch+1);
39         for(int j=1;j<=n;j++)
40         {
41             if(i==j)dis[i][i]=0;
42             else dis[i][j]=inf; 
43             if(ch[j]=='1')dis[i][j]=getdis(i,j);
44         }
45     }
46     floyd();
47     int id=0;
48     for(int i=1;i<=n;i++)
49     if(!field[i])dfs(i,++id);//染色遍历确定集合; 
50     
51     for(int i=1;i<=n;i++)
52     for(int j=1;j<=n;j++)
53     {
54         if(dis[i][j]==inf)continue;//说明不同集合 
55         dismx[i]=max(dismx[i],dis[i][j]);//i,j同一集合且获得i到其他点的最短路的最大路径;即i的直径 
56         field_max[field[i]]=max(field_max[field[i]],dismx[i]);//获得同一个集合里的最大直径 
57     }
58     double ans=inf;
59     for(int i=1;i<=n;i++)
60     for(int j=1;j<=n;j++)
61     {
62         if(field[i]!=field[j])
63         {    //如果不同集合,我们就加边,确定两个牧场的直径,对所有可行解取min; 
64             ans=min(max({dismx[i]+dismx[j]+getdis(i,j),field_max[field[i]],field_max[field[j]]}),ans);
65         }
66     }
67     printf("%.6lf",ans);
68     return 0;
69 }

 

posted @ 2021-12-16 12:36  matt-11  阅读(47)  评论(0)    收藏  举报