floyd + dfs染色。

重点是添加新的边之后的field的直径等于

1.原来两个field的直径

2.新的边长加从它的两个端点可以延伸的最大长度

这其中的最大值。

View Code
  1 /*
  2 ID: xjtuacm1
  3 PROG: cowtour
  4 LANG: C++
  5 */
  6 #include<iostream>
  7 #include<stack>
  8 #include<cstring>
  9 #include<cstdio>
 10 #include<queue>
 11 #include<algorithm>
 12 #include<set>
 13 #include<map>
 14 #include<vector>
 15 #include<cmath>
 16 using namespace std;
 17 const int N = 150;
 18 const double DINF = 1e30;
 19 
 20 struct Point
 21 {
 22     int x, y;
 23 } pes[N];
 24 
 25 int adj[N][N];
 26 int color[N];
 27 
 28 double dis[N][N];
 29 double maxDis[N];
 30 double dia[N];
 31 int n;
 32 
 33 void floodfill(int cur, int tag)
 34 {
 35     color[cur] = tag;
 36     for(int i = 0; i!= n; i++)
 37     {
 38         if(adj[cur][i] && color[i] == -1)
 39         {
 40             floodfill(i, tag);
 41         }
 42     }
 43 }
 44 
 45 int find_component()
 46 {
 47     int cnt = 0;
 48     for(int i = 0; i < n; i++)
 49         if(color[i] == -1)
 50             floodfill(i, cnt++);
 51     return cnt;
 52 }
 53 
 54 double dist(int a, int b)
 55 {
 56     if(!adj[a][b])
 57         return DINF;
 58 
 59     return sqrt((pes[a].x - pes[b].x) * (pes[a].x - pes[b].x)
 60                 + (pes[a].y - pes[b].y) * (pes[a].y - pes[b].y));
 61 }
 62 
 63 void floyd()
 64 {
 65     for(int i = 0; i!= n; i++)
 66         for(int j = 0; j!= n; j++)
 67             dis[i][j] = dist(i, j);
 68 
 69     for(int k = 0; k!= n; k++)
 70         for(int i = 0; i!= n; i++)
 71             for(int j = 0; j!= n; j++)
 72                 dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);
 73 }
 74 
 75 int main(int argc, char *argv[])
 76 {
 77 #ifdef ACM
 78     freopen("in", "r", stdin);
 79 #else
 80     freopen("cowtour.in", "r", stdin);
 81     freopen("cowtour.out", "w", stdout);
 82 #endif // ACM
 83 
 84     scanf("%d\n", &n);
 85     for(int i = 0; i!= n; i++)
 86     {
 87         scanf("%d %d\n", &pes[i].x, &pes[i].y);
 88     }
 89     for(int i = 0; i!= n; i++)
 90     {
 91         char line[N + 1];
 92         gets(line);
 93         for(int j = 0; j!= n; j++)
 94         {
 95             adj[i][j] = (line[j] == '0'? 0 : 1);
 96 
 97             dis[i][j] = dist(i, j);
 98 
 99         }
100     }
101 
102     memset(color, -1, sizeof(color));
103     int ncom = find_component();
104     floyd();
105 
106     for(int i = 0; i!= ncom; i++)
107         dia[i] = 0;
108 
109     for(int i = 0; i!= n; i++)
110     {
111         maxDis[i] = 0;
112         for(int j = 0; j!= n; j++)
113         {
114             if(i!= j && color[i] == color[j])
115             {
116                 maxDis[i] = max(maxDis[i], dis[i][j]);
117             }
118         }
119 
120         dia[color[i]] = max(dia[color[i]], maxDis[i]);
121     }
122 
123     double diameter = DINF;
124     for(int i = 0; i!= n; i++)
125         for(int j = 0; j!= n; j++)
126     {
127         if(color[i] == color[j])
128             continue;
129 
130         double d1 = 0;
131         double d2 = 0;
132         for(int k = 0; k!= n; k++)
133         {
134             if(i != k && color[i] == color[k])
135                 d1 = max(d1, dis[i][k]);
136 
137             if(j != k && color[j] == color[k])
138                 d2 = max(d2, dis[j][k]);
139         }
140 
141         double dist = sqrt( (pes[i].x - pes[j].x) * (pes[i].x - pes[j].x)
142                            + (pes[i].y - pes[j].y) * (pes[i].y - pes[j].y) );
143 
144         diameter = min(diameter,
145                        max(dist + d1 + d2,
146                            max(dia[color[i]], dia[color[j]])));
147     }
148 
149     printf("%.6lf\n", diameter);
150 
151     return 0;
152 }

BTW,对复杂代码的掌控能力还是不够。。虽然这道题有了完整思路,但是写不出完整的代码,最后还是参考了题解才写完...