USACO 2.4.3 Cow Tours
floyd + dfs染色。
重点是添加新的边之后的field的直径等于
1.原来两个field的直径 2.新的边长加从它的两个端点可以延伸的最大长度
这其中的最大值。
/*
ID: xjtuacm1
PROG: cowtour
LANG: C++
*/
#include<iostream>
#include<stack>
#include<cstring>
#include<cstdio>
#include<queue>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<cmath>
using namespace std;
const int N = 150;
const double DINF = 1e30;
struct Point
{
    int x, y;
} pes[N];
int adj[N][N];
int color[N];
double dis[N][N];
double maxDis[N];
double dia[N];
int n;
void floodfill(int cur, int tag)
{
    color[cur] = tag;
    for(int i = 0; i!= n; i++)
    {
        if(adj[cur][i] && color[i] == -1)
        {
            floodfill(i, tag);
        }
    }
}
int find_component()
{
    int cnt = 0;
    for(int i = 0; i < n; i++)
        if(color[i] == -1)
            floodfill(i, cnt++);
    return cnt;
}
double dist(int a, int b)
{
    if(!adj[a][b])
        return DINF;
    return sqrt((pes[a].x - pes[b].x) * (pes[a].x - pes[b].x)
                + (pes[a].y - pes[b].y) * (pes[a].y - pes[b].y));
}
void floyd()
{
    for(int i = 0; i!= n; i++)
        for(int j = 0; j!= n; j++)
            dis[i][j] = dist(i, j);
    for(int k = 0; k!= n; k++)
        for(int i = 0; i!= n; i++)
            for(int j = 0; j!= n; j++)
                dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);
}
int main(int argc, char *argv[])
{
#ifdef ACM
    freopen("in", "r", stdin);
#else
    freopen("cowtour.in", "r", stdin);
    freopen("cowtour.out", "w", stdout);
#endif // ACM
    scanf("%d\n", &n);
    for(int i = 0; i!= n; i++)
    {
        scanf("%d %d\n", &pes[i].x, &pes[i].y);
    }
    for(int i = 0; i!= n; i++)
    {
        char line[N + 1];
        gets(line);
        for(int j = 0; j!= n; j++)
        {
            adj[i][j] = (line[j] == '0'? 0 : 1);
            dis[i][j] = dist(i, j);
        }
    }
    memset(color, -1, sizeof(color));
    int ncom = find_component();
    floyd();
    for(int i = 0; i!= ncom; i++)
        dia[i] = 0;
    for(int i = 0; i!= n; i++)
    {
        maxDis[i] = 0;
        for(int j = 0; j!= n; j++)
        {
            if(i!= j && color[i] == color[j])
            {
                maxDis[i] = max(maxDis[i], dis[i][j]);
            }
        }
        dia[color[i]] = max(dia[color[i]], maxDis[i]);
    }
    double diameter = DINF;
    for(int i = 0; i!= n; i++)
        for(int j = 0; j!= n; j++)
    {
        if(color[i] == color[j])
            continue;
        double d1 = 0;
        double d2 = 0;
        for(int k = 0; k!= n; k++)
        {
            if(i != k && color[i] == color[k])
                d1 = max(d1, dis[i][k]);
            if(j != k && color[j] == color[k])
                d2 = max(d2, dis[j][k]);
        }
        double dist = sqrt( (pes[i].x - pes[j].x) * (pes[i].x - pes[j].x)
                           + (pes[i].y - pes[j].y) * (pes[i].y - pes[j].y) );
        diameter = min(diameter,
                       max(dist + d1 + d2,
                           max(dia[color[i]], dia[color[j]])));
    }
    printf("%.6lf\n", diameter);
    return 0;
}
BTW,对复杂代码的掌控能力还是不够。。虽然这道题有了完整思路,但是写不出完整的代码,最后还是参考了题解才写完…