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

本次,我主要给大家讲一讲有关这一题的Prim算法

首先我们来讨论一下:

什么是最小生成树?

  1. 无回路,且包含原图中的n-1条边
  2. 包含原图中的全部顶点
  3. 边的权重和在所有其他生成树中最小
  4. 最小生成树存在,则该图一定连通。反过来一样,图连通,则最小生成树一定存在

那么如何构建满足以上条件的生成树?
Prim算法构建最小生成树,
简单来说就是在图中,从某一顶点出发,逐步构建让一棵小树逐渐长大
用一个例子来说明更清晰点吧!首先看下面一张无向网图
在这里插入图片描述
要构造这张图的最小生成树,首先,假设我们从V0顶点开始出发,
也就是以V0为根结点开始建树,接着往外扩展,从与V0顶点相邻的顶点中找出权值最小的顶点,可以看到是V6,所以把V6和V0连接起来在这里插入图片描述
也就是把V6收录进了这棵最小生成树中了。
接着继续,从当前树中顶点的邻接点中 (也就是V0和V6的邻接点中,找出权值最小的顶点)。可以看到是V1,所以把V1也接入最小生成树中。在这里插入图片描述
然后继续,到V2结点,也接入最小生成树中
在这里插入图片描述
因为不能形成回路
所以V2和V6之间不能连接(虽然权值最小,等于3)
V0和V1之间也不能连接。所以只能V6和V4连接在这里插入图片描述
最后V4和V5连接,V4再和V3连接,就完成了这棵最小生成树的构建了。

本图为最小生成树的最终模型在这里插入图片描述

好了,基本Prim算法已实现,回归正题

题目传送门

首先,按照做题的方法,我们先把数据全部读入;

然后把两条田地修管子的费用全部求出来,注意本题是无向的;
所以way[i][j]=way[j][i];
还要注意一点,就是如果way[i][j]<c要把way[i][j]设为达到不了 (即设成很大的数)

接着用一个p[]存储当前点有没有用过;

剩下的我给个关键代码吧 (就是Prim算法关键部分)

for(int i=1;i<=n;i++) cnt[i]=way[1][i];
	for(int i=1;i<=n-1;i++)
	{
		int k=0,ji=maxn;
		for(int j=1;j<=n;j++) if(cnt[j]<ji&&!p[j]) ji=cnt[j],k=j;
		if(ji==maxn){
			printf("-1");
			return 0;
		}
		ans+=ji;
		p[k]=1;
		for(int j=1;j<=n;j++)
		if(cnt[j]>way[k][j]&&!p[j]) cnt[j]=way[k][j];
	}

最后输出就可以了

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章