USACO Section 2.4 Cow Tours (Floyd+并查集)

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/rockzh1993/article/details/49621753

用floyd计算每个点可达的最短距离,然后统计每个点可达距离的最大长度。然后用并查集计算每个点所属的集合,枚举两个不同集合a、b里的两个点i、j,从所有的max

{edge[a],edge[b],distance(i,j)+l(i)+l(j)},其中edge[x]表示集合x的直径,distance(x,y)表示x和y点的距离,l(x)表示点x可达距离的最大长度。

#include <iostream>
#include <cstdio>
#include <map>
#include <vector>
#include <string>
#include <stack>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
/*
ID: kkkwjx1
PROG: cowtour
LANG: C++
*/
typedef long long LL;
const int maxn=155;
const double inf=1e15;
double g[maxn][maxn];
int x[maxn],y[maxn];
double edge[maxn];
double dist(double x1,double y1,double x2,double y2)
{
    return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}

int father[maxn];
int find(int p)
{
    return p==father[p]?p:father[p]=find(father[p]);
}
void merge(int a,int b)
{
    int fa=find(a),fb=find(b);
    if(fa!=fb)
        father[fa]=fb;
}

int main()
{
    freopen("cowtour.in","r",stdin);
    freopen("cowtour.out","w",stdout);
    int n;
    scanf("%d",&n);
    for(int i=1; i<=n; ++i)
        scanf("%d%d",&x[i],&y[i]);
    for(int i=0; i<=n; ++i)
        for(int j=0; j<=n; ++j)
            if(i==j)
                g[i][j]=0;
            else
                g[i][j]=inf;
    for(int i=1; i<=n; ++i)
        father[i]=i;
    for(int i=1; i<=n; ++i)
    {
        char str[maxn];
        scanf("%s",str);
        for(int j=1; j<=n; ++j)
        {
            if(str[j-1]=='1')
            {
                merge(i,j);
                g[i][j]=g[j][i]=dist(x[i],y[i],x[j],y[j]);
            }
        }
    }
    for(int k=1; k<=n; ++k)
    {
        for(int i=1; i<=n; ++i)
        {
            for(int j=1; j<=n; ++j)
                if(g[i][k]!=inf&&g[k][j]!=inf)
                    g[i][j]=min(g[i][j],g[i][k]+g[k][j]);
        }
    }
    for(int i=1; i<=n; ++i)
        for(int j=1; j<=n; ++j)
            if(g[i][j]!=inf)
                g[i][i]=max(g[i][i],g[i][j]);
    for(int i=1; i<=n; ++i)
    {
        int fa=find(i);
        edge[fa]=max(edge[fa],g[i][i]);
    }
    double ans=inf;
    for(int i=1; i<=n; ++i)
    {
        for(int j=i+1; j<=n; ++j)
        {
            int fa=find(i),fb=find(j);
            if(fa!=fb)
            {
                double dis=dist(x[i],y[i],x[j],y[j])+g[i][i]+g[j][j];
                dis=max(dis,max(edge[fa],edge[fb]));
                ans=min(ans,min(dis,res));
            }
        }
    }
    printf("%.6f\n",ans);
    return 0;
}


展开阅读全文

新人求教~~usaco的milking cow有一个程序不理解

10-13

三个农民每天清晨5点起床,然后去牛棚给3头牛挤奶。第一个农民在300秒(从5点开始计时)给他的牛挤奶,一直到1000秒。第二个农民在700秒开始,在 1200秒结束。第三个农民在1500秒开始2100秒结束。期间最长的至少有一个农民在挤奶的连续时间为900秒(从300秒到1200秒),而最长的无人挤奶的连续时间(从挤奶开始一直到挤奶结束)为300秒(从1200秒到1500秒)。 rnrn你的任务是编一个程序,读入一个有N个农民(1 <= N <= 5000)挤N头牛的工作时间列表,计算以下两点(均以秒为单位): rnrn最长至少有一人在挤奶的时间段。 rn最长的无人挤奶的时间段。(从有人挤奶开始算起) rnrn/*rn ID : irisflo1rn PROG : milk2rn LANG : C++rn*/rn#include rn#include rnusing namespace std;rnint a[5001], b[5001], n;rnvoid qsort(int l, int r, int a[5001])rnrn int i(l), j(r), k(a[(l + r) / 2]);rn dorn rn while (i <= j && a[i] < k) i++;rn while (i <= j && a[j] > k) j--;rn if (i <= j)rn rn a[0] = a[i]; a[i] = a[j]; a[j] = a[0];rn i++; j--;rn rn while (i <= j);rn if (l < j) qsort(l, j, a);rn if (i < r) qsort(i, r, a);rnrnint main(void)rnrn ifstream fin ("milk2.in");rn ofstream fout ("milk2.out");rn fin >> n;rn for (int i = 1; i <= n; i++)rn fin >> a[i] >> b[i];rn qsort(1,n,a);rn qsort(1,n,b);rn int l(a[1]), r(b[1]), point(1), ans1(0), ans2(0);rn dorn rn while (point < n && a[point + 1] <= r) point++; r = b[point];rn if (r - l > ans1) ans1 = r - l;rn point++; rn if (point <= n) l = a[point]; if (l - r > ans2) ans2 = l - r; r = b[point];rn while (point <= n);rn fout << ans1 << " " << ans2 << endl;rn return 0;rnrn能帮我注释一下么?我是新人,不太能看懂啊~~从qsort函数开始就不大能理解 论坛

没有更多推荐了,返回首页