CF 436D 最小生成树

设一个开头的虚节点,然后建稠密图,O(n^2)。使用prim。O(n^2),保存方案,没什么好说的。

#include <string.h>
#include <stdio.h>
#include <algorithm>
#include <vector>
using namespace std;
int k,w,n,m;
int cnt;
int map[1005][1005];
char data[1002][11][11];
int father[1005];
struct node
{
	int pre,to;
}save[1005];
int prim()
{
	int ans=0;
	int i,j;
	int vis[1005];
	int dis[1005];
	memset(vis,0,sizeof(vis));
	memset(dis,0x7f,sizeof(dis));
	int inf=dis[0];
	vis[0]=1;
	int min;
	for (i=1;i<=k;i++)
	{
		dis[i]=map[0][i];
		father[i]=0;
	}
	int u;
	for (i=0;i<k;i++)
	{
		min=inf;
		for (j=0;j<=k;j++)
			if (!vis[j] && min>dis[j])
			{
				
				u=j;
				min=dis[j];
			}
		vis[u]=1;
		ans+=dis[u];
		save[cnt].pre=u;save[cnt].to=father[u];
		cnt++;
		for (int p=0;p<=k;p++)
			if (u!=p && !vis[p])
				if (dis[p]>map[u][p])
				{
					dis[p]=map[u][p];
					father[p]=u;
				}
	}
	return ans;
}
		
int main()
{
	int i;
	while (scanf("%d%d%d%d",&n,&m,&k,&w)!=EOF)
	{
		cnt=0;
		for (i=1;i<=k;i++)
		{
			for (int j=0;j<n;j++)
				scanf("%s",data[i][j]);
		}
		for (i=1;i<=k;i++)
		{
			map[0][i]=n*m;
			map[i][0]=m*n;
		}
		int tmp;
		for (i=1;i<=k;i++)
		{
			for (int j=i+1;j<=k;j++)
			{
				tmp=0;
				for (int p=0;p<n;p++)
					for (int q=0;q<m;q++)
						if (data[i][p][q]!=data[j][p][q])
							tmp+=w;
				map[i][j]=tmp;
				map[j][i]=tmp;
			}
		}
		printf("%d\n",prim());
		for (i=0;i<cnt;i++)
			printf("%d %d\n",save[i].pre,save[i].to);
	}
	return 0;
}

  

posted on 2014-06-15 00:27  six_god  阅读(223)  评论(0编辑  收藏  举报

导航