poj_3026 BFS+Prim

题目说明:

这道题槽点太多,除了discuss里的输入数据的问题,自己犯的错误是一直TLE,不得不考虑降低复杂度,由原来的n^2/2 * O(bfs)   降到   n * O(bfs)  。

改进前:相当于对任意两点算一次BFS:有n个点自然算n^2次BFS

<span style="font-size:18px;">void constructGraph(int num,int target[][2])
{
	for (int i = 1; i <= num; i++)
	{
		for (int j = 1; j <= num; j++)
		{
			//calculate the value between target[i] --->  target[j]
			if (graph[i][j]==-1)
				graph[i][j]=graph[j][i] = bfs(i-1,j-1,target);
		}
	}
}</span>
改进后:对每个点算一次BFS,这一次直接算到底,这个点和其他所有点的distance都算出,自然是算n次BFS。

void constructGraph(int num,int target[][2])
{
	for (int i = 0; i<num; i++)
	{
		bfs(target,i);
		for (int j = 0; j<num; j++)
			graph[i+1][j+1] = dist[target[j][0]][target[j][1]];
	}
}

完整代码:

#include<iostream>
#include<fstream>
#include<queue>

using namespace std;

const int MAX = 102;
const int MAXCOST = 0x7fffffff;

int graph[MAX][MAX], dist[MAX][MAX];
char map[MAX][MAX];
int num,row, col;
int dir[4][2] = {
	0, -1,  //up
	0, 1,  //down
	-1, 0,  //left
	1, 0,  //right
};

struct Node{
	int x, y;
};

int prim(int graph[][MAX], int n)
{
	int sum=0;
	int lowcost[MAX];
	int mst[MAX];
	for (int i = 1; i <= n; i++)
	{
		lowcost[i] = graph[1][i];
		mst[i] = 1;
	}
	mst[1] = 0;
	for (int i = 1; i <= n - 1; i++)
	{
		int min=MAXCOST, minid=0;
		for (int j = 2; j <= n; j++)
		{
			if (lowcost[j] != 0 && lowcost[j] < min)
			{
				min = lowcost[j];
				minid = j;
			}
		}
		lowcost[minid] = 0;
		sum += min;
		for (int j = 2; j <= n; j++)
		{
			if (graph[minid][j] < lowcost[j])
			{
				lowcost[j] = graph[minid][j];
				mst[j] = minid;
			}
		}
	}
	return sum;
}

void bfs(int target[][2],int i)
{
	queue<Node> que;
	Node node;
	node.x = target[i][0];
	node.y = target[i][1];
	que.push(node);
	dist[node.x][node.y] = 0;
	int flag[MAX][MAX];
	memset(flag, 0, sizeof(flag));
	flag[node.x][node.y] = 1;
	while (!que.empty())
	{
		Node now,next;
		now = que.front(); 
		que.pop();
		for (int i = 0; i<4; i++)
		{
			int x = now.x + dir[i][0];
			int y = now.y + dir[i][1];
			if (x >= 0 && x<row && y >= 0 && y<col && map[x][y] != '#' && !flag[x][y])
			{
				next.x = x;
				next.y = y;
				que.push(next);
				dist[x][y] = dist[now.x][now.y] + 1;
				flag[x][y] = 1;
			}
		}
	}
}

void constructGraph(int num,int target[][2])
{
	for (int i = 0; i<num; i++)
	{
		bfs(target,i);
		for (int j = 0; j<num; j++)
			graph[i+1][j+1] = dist[target[j][0]][target[j][1]];
	}
}

int main()
{
	int cases;
	//ifstream in("input.txt");
	cin >> cases;
	for (int i = 1; i <= cases; i++)
	{
		num = 1;
		int target[MAX][2];
		//construct the maze map
		cin >> col >> row;
		gets(map[0]);
		for (int p = 0; p < row; p++)
		{
			gets(map[p]);
			for (int q = 0; q < col; q++)
			{
				switch (map[p][q])
				{
					case 'A':
						target[num][0] = p;
						target[num++][1] = q;
						break;
					case 'S':
						target[0][0] = p;
						target[0][1] = q;
						break;
					default:
						break;
				}
			}
		}
		constructGraph(num,target);
		cout << prim(graph,num) << endl;
	}
	//system("pause");
	return 0;
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值