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

浙公网安备 33010602011771号