[USACO2.4]牛的旅行 Cow Tours
阿新 • • 發佈:2020-08-11
題目描述:這裡
思路:
首先,先對整個圖進行判連通塊,用並查集即可(這一步很重要,因為這可以降低時間複雜度)。
其次,對整個圖用求區域內的最短路。
然後,進行暴力,對於不在一個連通塊內的兩個點,嘗試連線它們,求直徑的最小值。
注意點:將兩個牧場連通後,直徑如果要經過新路,可能還比原來牧場的直徑小,所以要進行特判。
程式碼部分:
#include<bits/stdc++.h> using namespace std; const long double INF = 0x3f3f3f3f3f3f3f3f; struct dot { int x, y; }temp[155]; long double len(int x, int y) { return (long double)sqrt((long double)(temp[x].x - temp[y].x) * (long double)(temp[x].x - temp[y].x) + (long double)(temp[x].y - temp[y].y) * (long double)(temp[x].y - temp[y].y)); } int n; long double d[155][155]; long double dis[155]; void floyed() { for(int k = 1;k <= n;k++) for(int i = 1;i <= n;i++) for(int j = 1;j <= n;j++) if(d[i][k] != INF && d[k][j] != INF && d[i][j] > d[i][k] + d[k][j]) d[i][j] = d[i][k] + d[k][j]; } int fa[155]; void init() { for(int i = 1;i <= n;i++) fa[i] = i; } int find(int x) { if(fa[x] == x) return x; return fa[x] = find(fa[x]); } void merge(int x, int y) { fa[find(x)] = find(y); } int main() { cin >> n; init(); for(int i = 1;i <= n;i++) cin >> temp[i].x >> temp[i].y; for(int i = 1;i <= n;i++) for(int j = 1;j <= n;j++) { char c; cin >> c; if(c == '1') { d[i][j] = len(i, j); merge(i, j); } else d[i][j] = INF; } floyed(); long double ans = 0x3f3f3f3f3f3f3f3f, sum = 0, maxa = INT_MIN, maxb = INT_MIN; int mina, minb; for(int i = 1;i <= n;i++) for(int j = i + 1;j <= n;j++) if(find(i) != find(j)) { sum += len(i, j); mina = i; minb = j; for(int k = 1;k <= n;k++) if(find(mina) == find(k) && k != mina) { if(d[mina][k] != INF) maxa = max(maxa, d[mina][k]); if(d[k][mina] != INF) maxa = max(maxa, d[k][mina]); } if(maxa >= 0) sum += maxa; for(int k = 1;k <= n;k++) if(find(minb) == find(k) && k != minb) { if(d[minb][k] != INF) maxb = max(maxb, d[minb][k]); if(d[k][minb] != INF) maxb = max(maxb, d[k][minb]); } if(maxb >= 0) sum += maxb; ans = min(ans, sum); sum = 0; maxa = INT_MIN, maxb = INT_MIN; } for(int i = 1;i <= n;i++) for(int j = 1;j <= n;j++) if(d[i][j] != INF) dis[i] = max(dis[i], d[i][j]); for(int i = 1;i <= n;i++) ans = max(ans, dis[i]); cout << fixed << setprecision(6) << ans << endl; return 0; }