[USACO08OCT]打井Watering Hole
本题看似很难,实际上就是一道简单的图论题——只要你能想清楚图中有几个点。
这个时候大部分人会喷我了,这多简单,不就是n个点吗?
不,你错了,这个东西虽说有点坑,其实有n+1个点
然后呢?这还需要然后吗,直接上代码不就好起来了吗?{斜眼笑}
代码如下:
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
#define MAXN 302
#define info 100000000
typedef int elemtype;
int s=0;
void prim(int mat[][MAXN],int n) //普利姆算法求最小生成树
{
elemtype lowcost[MAXN];//表示边(i,closest[i])的权值
int closest[MAXN];//表示U中的一个顶点。
//该顶点和V-U中的一个顶点构成的边(i,closest[i])具有最小的权值
int i,j,k,mini,ret=0;
//int maxi=0; //最长的那个边
bool v[MAXN];
for (i=0;i<n;i++) //Initialize
{
lowcost[i]=mat[0][i];
closest[i]=0;
v[i]=false;
}
v[0] = true;
for (i=0;i<n-1;i++)
{
k=0;
mini=info;
for (j=0;j<n;j++)
{
if (!v[j] && lowcost[j]<mini)
{
mini=lowcost[j];
k=j;
}
}
v[k]=true;
//if (maxi<lowcost[k]) //为了求最长边的最小值
//maxi=lowcost[k];
ret+=lowcost[k];
//cout<<k<<" "<<closest[k]<<" "<<lowcost[k]<<endl;//打印边
s+=lowcost[k];
for (j=0;j<n;j++)
{
if (!v[j] && mat[k][j]<lowcost[j])
{
lowcost[j]=mat[k][j];
closest[j]=k;
}
}
}
}
int main()
{
int i,j;
int n,k; //n农场总数
int mat[MAXN][MAXN];//邻接矩阵
cin>>n;
for (k=1;k<=n;k++)
{
cin>>i;
mat[0][k]=i;
mat[k][0]=i;
}
for (i=1;i<=n;i++)
{
for (j=1;j<=n;j++)
{
cin>>k;
mat[i][j]=k;
mat[j][i]=k;
}
}
prim(mat,n+1); //从0到n,共n+1
cout<<s<<endl;
return 0;
}