HDU 1102 Constructing Roads(最小生成树:Prim | Kruskal)

传送门:http://acm.hdu.edu.cn/showproblem.php?pid=1102

题意:先给你一个邻接矩阵,然后给你几个已连接的点,求没连接的几块最少要多长的线连接。

一、Prim算法

思路:按点分为S T两块,每次从T块中取出一个点,放入S中。取点满足:T中与S块距离最近的。因为每次取的都是最小边,故可保证连接线最小。

AC代码:

#include<iostream>
using namespace std;
#define INF 0x3f3f3f3f
int n,ans;
int map[101][101];
int dis[101],vis[101];
//vis界定S T集合;dis记录S T最短距离 
void Prim()
{
	for(int i=1;i<=n;i++)
	{
		dis[i]=map[1][i];
		vis[i]=0;
	}
	dis[1]=0;
	vis[1]=1;
	//预处理地图 
	int k,tmp;
	for(int i=1;i<=n;i++)
	{
		tmp=INF;
		for(int j=1;j<=n;j++)        //这个循环找出T中距S最近的点 
			if(!vis[j]&&tmp>dis[j])
			{
				k=j;
				tmp=dis[j];
			}
		if(tmp==INF) break;//如果找不到,证明T没有点了,退出 
		vis[k]=1;           //找到了,放入S集合 
		ans+=dis[k];       //加上最短距离 
		for(int j=1;j<=n;j++)    //这个循环更新 加入新点后S与T的最短距离 
            if(!vis[j]&&dis[j]>map[k][j])
                dis[j]=map[k][j];
	} 
}
int main()
{
	while(cin>>n)
	{
		for(int i=1;i<=n;i++)
			for(int j=1;j<=n;j++)
				cin>>map[i][j];//建立地图 
		int k,a,b;
		cin>>k;
		while(k--)
		{
			cin>>a>>b;
			map[a][b]=map[b][a]=0;	//已连接的不用再考虑,所以清零		
		}
		ans=0;
		Prim();//Prim算法处理 
		cout<<ans<<endl; 
	}
	return 0;
}

二、Kruskal算法

思路:按连接线的长短排序,然后按照顺序判断两点是否已连接,如果已连接则continue,否则加上这条连接线。

AC代码:

#include<iostream>
#include<algorithm>
using namespace std;
struct node
{
	int u,v;
	int cap;//记录u到v的距离 
}edge[10001];
int n,cnt,ans;
int father[101];
//
void addedge(int cu,int cv,int cw)
{
	edge[cnt].cap=cw;
	edge[cnt].u=cu;
	edge[cnt].v=cv;
	cnt++;
}
//将每个点的父节点置为自己 
void makeSet()
{
	for(int i=1;i<=n;i++)
	{
		father[i]=i;
	}
}
//查找父节点 
int findSet(int x)
{
	if(x!=father[x])
	{
		father[x]=findSet(father[x]);
	}
	return father[x];
}
//定义结构体排序方式 
bool cmp(node a,node b)
{
	return a.cap<b.cap;
}
// 
void Kruskal()
{
	sort(edge,edge+cnt,cmp);
	for(int i=0;i<cnt;i++)
	{
		int fx=findSet(edge[i].u);
		int fy=findSet(edge[i].v); 
		if(fx==fy) continue;
		ans+=edge[i].cap;//加上这条线
		father[fy]=fx;//连通线
	} 
}

int main()
{
	while(cin>>n)
	{
		makeSet();
		cnt=0;
		int w;
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=n;j++)
			{
				cin>>w;
				addedge(i,j,w);
			} 
		}
		int k,a,b;
		cin>>k;
		while(k--)
		{
			cin>>a>>b;
			int fx=findSet(a);
			int fy=findSet(b);  
			father[fy]=fx;
		}
		ans=0;
		Kruskal(); 
		cout<<ans<<endl;
	}
	return 0;
} 

猜你喜欢

转载自blog.csdn.net/jack_jxnu/article/details/81474615