P1550 [USACO08OCT]打井Watering Hole (最小生成树+Prim算法)
题目背景
John的农场缺水了!!!
题目描述
Farmer John has decided to bring water to his N (1 <= N <= 300) pastures which are conveniently numbered 1..N. He may bring water to a pasture either by building a well in that pasture or connecting the pasture via a pipe to another pasture which already has water.
Digging a well in pasture i costs W_i (1 <= W_i <= 100,000).
Connecting pastures i and j with a pipe costs P_ij (1 <= P_ij <= 100,000; P_ij = P_ji; P_ii=0).
Determine the minimum amount Farmer John will have to pay to water all of his pastures.
POINTS: 400
农民John 决定将水引入到他的n(1<=n<=300)个牧场。他准备通过挖若
干井,并在各块田中修筑水道来连通各块田地以供水。在第i 号田中挖一口井需要花费W_i(1<=W_i<=100,000)元。连接i 号田与j 号田需要P_ij (1 <= P_ij <= 100,000 , P_ji=P_ij)元。
请求出农民John 需要为连通整个牧场的每一块田地所需要的钱数。
输入输出格式
输入格式:第1 行为一个整数n。
第2 到n+1 行每行一个整数,从上到下分别为W_1 到W_n。
第n+2 到2n+1 行为一个矩阵,表示需要的经费(P_ij)。
输出格式:只有一行,为一个整数,表示所需要的钱数。
输入输出样例
输出样例#1:
9
说明
John等着用水,你只有1s时间!!!
将打井看成0结点,打井的花费就相当于0结点到各个结点的距离
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN=310;
struct Node
{
int adjvex;
int lowcost;
}closedge[MAXN];
int cost[MAXN][MAXN];
int MinV_Ucost(int n) //这个函数是用来找V集合的点到U集合点的最短cost(当然是只有两个点)
{
int MINN=0x3f3f3f3f;
int i,v;
for(i=0;i<=n;i++)
{
if(closedge[i].lowcost!=0) //等于0的就已经进U集合了,不做考虑,这样避免了生成环。
{
if(closedge[i].lowcost<MINN)
{
MINN=closedge[i].lowcost;
v=i;
}
}
}
if(MINN==0x3f3f3f3f)
{
printf("不连通\n"); //原图不连通,至少有一个不为INF才连通啊
return 0;
}
else
return v;
}
int Prim(int u,int n) //u是U集合的第一个点,可以认为假设
{
int i,j;
int v;
int ans=0;
closedge[u].lowcost=0; //=0就是将该结点放入U集合中
for(i=0;i<=n;i++)
{
if(i!=u)
{
closedge[i].adjvex=u; //i是在V集合中的点,同时说明第一个点是没有adjvex的
closedge[i].lowcost=cost[u][i];
}
}
for(j=0;j<n;j++) //第一个点已经确定,进入U,还剩n-1个点没进U集合
{
v=MinV_Ucost(n);
ans+=closedge[v].lowcost;
/*u=closedge[v].adjvex; //这样就多了个可以输出两邻接点的功能
printf("%d %d\n",u,v);*/
closedge[v].lowcost=0; //把新点加入U集合。
for(i=0;i<=n;i++) //更新V各点到U各点的最短距离。
{
if(cost[v][i]<closedge[i].lowcost) //在U中的点是0,所以if语句无视
{
closedge[i].lowcost=cost[v][i];
closedge[i].adjvex=v;
}
}
}
return ans;
}
int main()
{
int n;
scanf("%d",&n);
int i,j;
for(i=1;i<=n;i++)
{
scanf("%d",&cost[0][i]);
}
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
scanf("%d",&cost[i][j]);
printf("%d\n",Prim(0,n));
return 0;
}