poj 3026

挺直接的一个题  哎   想复杂了

题意:把n*m矩阵中的字母最小生成树 求它的边权值之和  只有字母可以分叉  多了一个提取点的过程

思路:prime  算法的简单应用

#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
char map[55][55];
int node[55][55];
int edge[111][111];
int nsum;
struct Node
{
	int x,y;
	int t;
};
int m,n;
int dir[4][2]={1,0,-1,0,0,-1,0,1};
void bfs(int x,int y)
{
	Node now,next;
	queue<Node> q;
	now.x=x,now.y=y,now.t=0;
	int i,j;
	int v[55][55];
	q.push(now);
	for(i=0;i<n;i++)
		for(j=0;j<m;j++)
			v[i][j]=999999999;
	v[x][y]=0;
	while(!q.empty())
	{
		now=q.front();q.pop();
		if(node[now.x][now.y])
			edge[node[x][y]][node[now.x][now.y]]=now.t;
		for(i=0;i<4;i++)
		{
			int xx=now.x+dir[i][0];
			int yy=now.y+dir[i][1];
			if(xx<0||xx>=n||yy<0||yy>=m)
				continue;
			if(map[xx][yy]=='#')
				continue;
			if(v[xx][yy]>now.t+1)
			{
				v[xx][yy]=now.t+1;
				next.x=xx;
				next.y=yy;
				next.t=now.t+1;
				q.push(next);
			}
		}
	}
	return ;
}
void prime()
{
	int sum=0;
	int s[111];
	memset(s,0,sizeof(s));
	int dist[111];
	int i,j;
	dist[1]=0;
	s[1]=1;
	for(i=2;i<=nsum;i++)
		dist[i]=edge[1][i];
	dist[1]=0;
	for(i=1;i<=nsum;i++)
	{
		int min=99999999;
		int v=-1;
		for(j=1;j<=nsum;j++)
		if(!s[j]&&dist[j]<min)
		{
			min=dist[j];
			v=j;
		}
		if(v==-1) break;
		s[v]=1;
		sum+=dist[v];
		for(j=1;j<=nsum;j++)
			if(dist[j]>edge[v][j])
				dist[j]=edge[v][j];
	}
	cout<<sum<<endl;
}
int main()
{
	
	int t,i,j;
	char s[100];
	scanf("%d",&t);
	while(t--)
	{
		nsum=0;
		memset(node,0,sizeof(node));
		scanf("%d%d",&m,&n);
		gets(s);
		for(i=0;i<n;i++)
		{
			gets(map[i]);
			for(j=0;j<m;j++)
			{
				if(map[i][j]=='S'||map[i][j]=='A')
					node[i][j]=++nsum;
			}
		}
		for(i=1;i<=nsum;i++)
			for(j=1;j<=nsum;j++)
				edge[i][j]=99999999;
		for(i=0;i<n;i++)
			for(j=0;j<m;j++)
				if(node[i][j])
					bfs(i,j);
		prime();
	}
	return 0;
}


			

 

posted @ 2014-06-08 15:06  _一千零一夜  阅读(196)  评论(0编辑  收藏  举报