prim及其练习

关于prim,其实我今天才学...

prim其实就是最小生成树的一种算法,严格每次的找最小边连到树上。看书上的代码看不懂,于是就自己大胆用堆优化写prim。

搞了很长时间,经过不写努力,还是搞出来了。

代码如下:

inline void prim()
{
    priority_queue<pair<int,int> >q;
    q.push(make_pair(0,m));
    while(ans<m)
    {
        int y=q.top().second;
        int v=-q.top().first;q.pop();
        if(vis[y]!=1)
        {
            minn+=v;ans++;vis[y]=1;
            for(int i=link[y];i;i=a[i].next)
            {
                int y1=a[i].y;
                int v1=a[i].v;
                q.push(make_pair(-v1,y1));
            }
        }
    }
}

有点简陋,但个人还是觉得比较理解,也就是每次加进去一个点,把这个点能连到的点与边权加进队列。之后取出最小的边,判断是否在树里,直到最后所有的点都在树里,prim结束。最小生成树也就完成了。

不说了,来看一道"裸题":

 猛看这道题以为就是练格式的,之后就发现不对了。他要保证的是每个地点有水即不一定要连成一个树,还可以在连起来的代价大于打井的代价时选择打井。连起来的大家都会,不就是连个最小生成树嘛,但是加上打井就有疑问,怎样处理好打井与用管道连起来的关系就是这道题的难点所在。

大家可以这样想:打井之后就不在树里,那我们最小生成树就无法完成。这时怎样将打井和树联系起来就是要思考的问题了。既然打井之后不在树里,哪我们为什么不能把它加进树里,即一个打井费用就是一个边,一共有n打井费用,即n条边,那就可以再加一个点,使其他点到这个点的距离就是那个点的打井费用,这样一共(n+1)个点跑最短路,与n所连的点就是打井的点,最小树也就完成了。

以下是代码:

#include<bits/stdc++.h>
using namespace std;
int n,tot,minn,link[100000],m,ans,vis[100000];
struct bian
{
	int y,v,next;
};
bian a[1000000];
inline int read()
{
	int x=0,ff=1;
	char ch=getchar();
	while(!isdigit(ch))
	{
		if(ch=='-') ff=-1;
		ch=getchar();
	}
	while(isdigit(ch))
	{
		x=(x<<1)+(x<<3)+(ch^48);
		ch=getchar();
	}
	return x*ff;
}
inline void add(int x,int y,int v)
{
	a[++tot].y=y;
	a[tot].v=v;
	a[tot].next=link[x];
	link[x]=tot;
}
inline void prim()
{
	priority_queue<pair<int,int> >q;
	q.push(make_pair(0,m));
	while(ans<m)
	{
		int y=q.top().second;
		int v=-q.top().first;q.pop();
		if(vis[y]!=1)
		{
			minn+=v;ans++;vis[y]=1;
			for(int i=link[y];i;i=a[i].next)
			{
				int y1=a[i].y;
				int v1=a[i].v;
				q.push(make_pair(-v1,y1));
			}
		}
	}
}
int main()
{
	//freopen("1.in","r",stdin);
	n=read();m=n+1;
	for(int i=1;i<=n;i++)
	{
		int v=read();
		add(m,i,v);add(i,m,v);
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			int v=read();
			if(i!=j) add(i,j,v);
		}
	}
	prim();
	cout<<minn<<endl;
	return 0;
}

  好了,就到这吧!

posted @ 2019-01-05 12:38  逆天峰  阅读(248)  评论(0编辑  收藏  举报
作者:逆天峰
出处:https://www.cnblogs.com/gcfer//