zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    1-22
    好久未更
    学习进度条 第十六周
    构建之法阅读笔记06
    返回一个整数数组中最大子数组的和(补充:输出该子数组)
    构建执法阅读笔记4
    第三周的学习进度情况
    构建之法阅读笔记03
    四则运算三
    安卓小程序之“标准体重计算器”
  • 原文地址:https://www.cnblogs.com/ay27/p/2800723.html
Copyright © 2011-2022 走看看