您的位置:首页 > 其它

uva 10397 Connect the Campus

2012-12-08 00:17 399 查看

最小生成树

和这道题是一样的,不过就是给出的数据不同hdu 1879 继续畅通工程

说来惭愧,写hdu那个的时候是1Y的,但是写这个却WA了一次是因为整个做法想错了

WA的想法是先用邻接矩阵建图,然后用一个had数组记录已经存在的边,在计算MST最小权值的时候如果是已有的边就不用算费用,所以需要adj数组去记录 边的信息

但是这个方法显然是错的,因为MST不是唯一的,如果最后MST的总权值最小,但是可能不同的MST用到的已有的边的条数是不同,用到的已有的边最少,那么需要额外付的费用就越好,如果是上面那样做,显然是WA

正确的做法就是把已有的边的权值赋值为0或者一个负数都可以(最好是0,那么就不用判断是否要并入花费中),因为这题是给出坐标,然后两点的距离就是权值,显然距离没有0或者负数的,因为题目说了不会有相同坐标的点。同样也不会有平行边,题目以说

然后就是prim算法或者kruskal算法都可以,直接模板就行了,因为已有的边权值为0,那么肯定会尽可能找到多的这些边的

所以其实adj数组使不需要的

这里给的是prim,kruskal就不给了

#include <cstdio>
#include <cstring>
#include <cmath>
#define INF 1000000000.000
#define N 800
double g

,lowcost
;
int x
,y
,cov
;
int n,m;

double dis(int i , int j)
{  return sqrt(1.0*(x[i]-x[j])*(x[i]-x[j])+1.*(y[i]-y[j])*(y[i]-y[j]));  }
void input()
{
for(int i=1; i<=n; i++)
scanf("%d%d",&x[i],&y[i]);
for(int i=1; i<=n; i++) g[i][i]=INF;
for(int i=1; i<=n; i++)
for(int j=i+1; j<=n; j++)
g[i][j]=g[j][i]=dis(i,j);
scanf("%d",&m);
for(int i=1; i<=m; i++)
{
int u,v;
scanf("%d%d",&u,&v);
g[u][v]=g[v][u]=0;
}
}

void prim()
{

double sum=0;
for(int i=1; i<=n; i++)
{ lowcost[i]=g[1][i]; cov[i]=0; }
cov[1]=1; lowcost[1]=0;

for(int nn=1; nn<n; nn++)
{
double min=INF;  int u=1;
for(int i=1; i<=n; i++)
if(!cov[i] && lowcost[i]<min)
{ min=lowcost[i]; u=i; }
cov[u]=1;
sum+=lowcost[u];

for(int v=1; v<=n; v++)
if(!cov[v] && g[u][v]<lowcost[v])
lowcost[v]=g[u][v];
}

printf("%.2f\n",sum);
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
input();
prim();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: