【usaco2013 mar】灌溉农田(irrigation.pas/cpp/c)//2018.1.28

题目

题目描述
由于最近缺少降雨,农夫约翰决定在他的N块农田之间建立一个供水管网。
每块的位置可以用一个二维坐标来表示(xi,yi),在第i块地和第j块地之间修建一个管道的话,代价是(xi - xj)^2 + (yi - yj)^2。
农夫约翰想要建立一个花费代价最小的供水管网,使得他所有的地都能被连接在一起(使得水能够通过一系列的管道流到各个田地里去)。
不幸的是,建造管道的人拒绝建造花费代价小于C的单条管道。
请帮助约翰计算最少需要花费多少代价,才能建成这个供水管网。
输入
第一行是两个正整数N和C。
第2行到第N+1行,每行两个整数,表示xi和yi。
输出
输出建立供水管网的最小代价,如果不能建立供水管网,就输出-1。
【数据规模】
1<=N<=2000,0<=xi,yi<=1000。

题目大意

求代价,建立一个花费代价最小的供水管网,拒绝建造花费代价小于C的单条管道。


解题思路

最小生成树,可以用(prim)算法做


代码

#include
#include
#include
using namespace std; 
int n,c,ans,an,b[2001][2001],d[2001];
struct node{
    int x,y; 
};
node a[2001]; 
bool u[2001]; 

int main()
{
    //freopen("irrigation.in","r",stdin); 
    //freopen("irrigation.out","w",stdout); 
    scanf("%d%d",&n,&c); 
    for (int i=1;i<=n;i++)
    scanf("%d%d",&a[i].x,&a[i].y);
    for (int i=1;i<=n;i++)
     for (int j=1;j<=n;j++)
        {
            b[i][j]=b[j][i]=(a[i].x-a[j].x)*(a[i].x-a[j].x)+(a[i].y-a[j].y)*(a[i].y-a[j].y); //求代价
            if (b[i][j]2147483647; 
        }   

   memset(d,0x7f,sizeof(d));  //Prim算法初始化d[]
   for (int i=1;i<=n;i++) d[i]=b[1][i]; 
   memset(u,true,sizeof(u)); u[1]=0;
   for (int i=1;i<=n-1;i++)
    {
        int k=0,minx=2147483647; 
        for (int j=1;j<=n;j++)
        if (u[j]&&d[j]//搜索最小边
        ans+=minx;
        if (minx==2147483647){printf("-1"); return 0;} //不能建造
        u[k]=false;
        for (int j=1;j<=n;j++)
         if (u[j]&&(b[k][j]//将新边加入集合后,有无比原来更为短的路径
    }
    printf("%d",ans); 
}

你可能感兴趣的:(最小生成树,图论(/基础/最小环),暴力(/模拟/字符串处理))