USACOCow Tours

来源:http://ace.delos.com/usacoprob2?a=ecro6SKAJN4&S=cowtour

看到题目的数据范围就知道这题应该用O(n^3)的算法做了,明显图论中Floyd算法就符合要求。

算法:

1.floyd求出任意两点的距离;

2.对于连通块A和连通块B,添加一条边e(u,v),把A和B联通,新的连通块称为C,则:

          dist[C]=dist[A][u]+dist[B][v]+e(u,v)         //dist[C]表示连通块C的最大距离,dist[A][u]表示连通块A中的点离u点的最远距离

3.枚举边e(u,v),找出最小的最大距离

具体的程序如下:

/*
ID:ay27272
PROG:cowtour
LANG:C++
*/

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <math.h>
using namespace std;

#define MINN 0.0001

struct node{
    int x,y;
    node()
    {
        x=y=0;
    }
    node(int a,int b)
    {
        x=a; y=b;
    }
};

double a[155][155];
struct node d[155];
int n;

double sqrtt(int a,int b)          //求出两点的距离
{
    double x1=d[a].x-d[b].x;
    double x2=d[a].y-d[b].y;
    return sqrt(x1*x1+x2*x2);
}

void floyd()
{
    for (int k=1;k<=n;k++)       //floyd算法模板
        for (int i=1;i<=n;i++)
        if (i!=k)
            for (int j=1;j<=n;j++)
            if (i!=j && k!=j)
            if (a[i][k]>MINN && a[k][j]>MINN &&
                (a[i][j]-a[i][k]-a[k][j]>MINN || a[i][j]<MINN))
                a[i][j]=a[i][k]+a[k][j];

    for (int i=1;i<=n;i++)       //记录每个点在其连通块中与其它点的最大距离
        for (int j=1;j<=n;j++)
        if (a[i][0]<a[i][j])
            a[i][0]=a[i][j];
}

int main()
{
    freopen("cowtour.in","r",stdin);
    freopen("cowtour.out","w",stdout);
    int xx,yy;
    scanf("%d",&n);
    for (int i=1;i<=n;i++)
    {
        scanf("%d%d\n",&xx,&yy);
        d[i]=node(xx,yy);
    }
    char s[200];
    for (int i=1;i<=n;i++)
    {
        gets(s);
        for (int j=0;j<n;j++)
        {
            if (s[j]=='0') a[i][j+1]=a[j+1][i]=0.0;
            else a[i][j+1]=a[j+1][i]=sqrtt(i,j+1);
        }
    }

    floyd();

    double maxx=10000000.0,k;
    for (int i=1;i<=n;i++)       //枚举边e(i,j)
        for (int j=1;j<=n;j++)
        if (i!=j)
        {
            k=sqrtt(i,j)+a[i][0]+a[j][0];
            if (a[i][j]<MINN && k<maxx)
            maxx=k;
        }
    for (int i=1;i<=n;i++)        //这一步不能省,因为有可能添加边后最大的距离并不在这个新的连通块中
        maxx=max(maxx,a[i][0]);

    printf("%.6lf\n",maxx);
    return 0;
}
原文地址:https://www.cnblogs.com/ay27/p/2800723.html