(紀中)1930. 灌溉農田(irrigation)【最小生成樹】

*(File IO): input:irrigation.in output:irrigation.out
時間限制: 1000 ms 空間限制: 128000 KB 具體限制


題目描述
由於最近缺少降雨,農夫約翰決定在他的N塊農田之間建立一個供水管網。每塊的位置可以用一個二維座標來表示xi,yi(xi,yi),在第i塊地和第j塊地之間修建一個管道的話,代價是(xixj)2+(yiyj)2(xi - xj)^2 + (yi - yj)^2。農夫約翰想要建立一個花費代價最小的供水管網,使得他所有的地都能被連接在一起(使得水能夠通過一系列的管道流到各個田地裏去)。不幸的是,建造管道的人拒絕建造花費代價小於C的單條管道。請幫助約翰計算最少需要花費多少代價,才能建成這個供水管網。


輸入
第一行是兩個正整數NNCC
22行到第N+1N+1行,每行兩個整數,表示xixiyiyi

輸出
輸出建立供水管網的最小代價,如果不能建立供水管網,就輸出1-1


樣例輸入
3 11
0 2
5 0
4 3

樣例輸出
46


數據範圍限制
1<=N<=2000,0<=xi,yi<=10001<=N<=2000,0<=xi,yi<=1000


提示
樣例中,約翰不能在4,3(4,3)5,0(5,0)之間建立管道,因爲這個管道的代價是1010。因此,他只能在0,2(0,2)5,0(5,0)之間修建一條管道,花費是2929,在0,2(0,2)4,3(4,3)之間修建一條管道,花費是1717,所以總的最小花費是29+17=4629+17=46


解題思路
這道題就是一道最小生成樹,可以採用普里姆算法.


代碼

#include<bits/stdc++.h>
using namespace std;
int n,c,x[2020],y[2020],a[2020][2020],v[2020],b[2020],minn,k,ans;
int main()
{
	freopen("irrigation.in","r",stdin);
    freopen("irrigation.out","w",stdout);
    scanf("%d%d",&n,&c);
    for(int i=1; i<=n; i++)
        for(int j=1; j<=n; j++)
            a[i][j]=999999999;
    for(int i=1; i<=n; i++)
    {
        scanf("%d%d",&x[i],&y[i]);
        for(int j=1; j<=i-1; j++)
            if((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j])>=c)
                a[i][j]=a[j][i]=(x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]);
    }
    v[1]=1;
    for(int i=2; i<=n; i++)
        b[i]=a[1][i];
    for(int j=1; j<=n-1; j++)
    {
        minn=999999998;
        for(int j=1; j<=n; j++)
            if(v[j]==0&&b[j]<=minn)
            {
                minn=b[j];
                k=j;
            }
        v[k]=1;
        ans+=b[k];
        for(int j=1; j<=n; j++)
            if(v[j]==0&&a[j][k]<=b[j])
                b[j]=a[j][k];
    }
    for(int i=1; i<=n; i++)
        if(!v[i])
        {
            printf("-1");
            return 0;
        }
    printf("%d",ans);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章