1. 程式人生 > 實用技巧 >P1522 [USACO2.4]牛的旅行 Cow Tours

P1522 [USACO2.4]牛的旅行 Cow Tours

圖被劃分成兩塊連通塊,現用一條邊將兩塊連通塊連線起來,使得圖的直徑(最遠的兩個點的最短距離)最小

  1. 既然要求最短路徑,觀察資料範圍,採用Floyd演算法求得任意兩點間最短路徑
  2. 然後列舉所有不連通的兩點,判斷以當前兩點間的距離為邊將連通塊連通得到的圖的直徑是否最小(在此之前要預處理出每個點在連通塊內所能抵達的最遠距離)
  3. 注意圖的直徑不一定橫跨兩個連通塊,有可能存在某一連通塊內部
  4. \(2,3\)兩種情況取較大者即可
const int N=155;
double g[N][N];
PII a[N];
double maxd[N];
int n;

double dis(PII a,PII b)
{
    return sqrt((a.fi-b.fi)*(a.fi-b.fi)+(a.se-b.se)*(a.se-b.se));
}

void floyd()
{
    for(int k=1;k<=n;k++)
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                g[i][j]=min(g[i][j],g[i][k]+g[k][j]);
}

int main()
{
    cin>>n;

    for(int i=1;i<=n;i++) cin>>a[i].fi>>a[i].se;

    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        {
            char c;
            cin>>c;
            g[i][j]=c-'0';
            if(g[i][j] == 1) g[i][j]=dis(a[i],a[j]);
            if(i!=j && !g[i][j]) g[i][j]=INF;
        }

    floyd();

    double res1=0;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        {
            if(g[i][j] != INF) maxd[i]=max(maxd[i],g[i][j]);
            res1=max(res1,maxd[i]);
        }

    double res2=INF;
    for(int i=1;i<=n;i++)
        for(int j=i+1;j<=n;j++)
            if(g[i][j] == INF)
                res2=min(res2,maxd[i]+maxd[j]+dis(a[i],a[j]));

    printf("%f\n",max(res1,res2));
    //system("pause");
}