PAT 1003 Emergency 深度优先搜索 (剪枝方案一,未优化)

#include<iostream>
#include<cstring>
using namespace std;

const int N = 1000;
const int INF = 100000000;

//图的邻接矩阵
int road[N][N];

//标记某一节点是否被访问过
bool isVisited[N];

//记录每一节点的权值
int team_num[N];

int dis[N];

//最短路径的数目
int path_num =0;

//最大的医疗队的数目
int g_max_team_num = 0;

void initData()
{
	int i,j;
	for(i=0; i<N; i++)
	{
		isVisited[i] = false;
		team_num[i] = 0;
		dis[i] = INF;//初始化为无穷大.
		for(j=0; j<N; j++)
		{
			if(j != i)
			{
				road[i][j] = INF;
				road[j][i] = INF;
			}
			//当i==j的时候,一定要赋值为0,否则当起点src和终点des相同的时候,test case是过不了的。
			else
				road[i][j] = 0;
		}
	}
}

//单源最短路径算法。
void Dijstra(int n,int src, int des)
{
	int i,j;
	for(i=0; i<n; i++)
		dis[i] = road[src][i];
	isVisited[src] = true;

	for(i=0; i<n-1; i++)//最多循环n-1次就足够了,选n-1个最小值。
	{
		int minDis = INF;
		int cur = 0;
		for(j=0; j<n; j++)
			if(!isVisited[j] && dis[j]<minDis)
			{
				minDis = dis[j];
				cur = j;
			}
		if(minDis == INF) //已经完成了连通路径的遍历。
			return;
		//dis[cur]为dis数组中的最小值,访问节点cur.
		isVisited[cur] = true;
		//更新Dis数组的内容.
		for(j=0; j<n; j++)
			if(road[cur][j] <INF && dis[j] > dis[cur] + road[cur][j])
				dis[j] = dis[cur] + road[cur][j];
	}
}

//深度搜索来得到最短路径的数目。
void dfs(int n,int cId,int des,int curDis,int curTeamsNum)
{
	isVisited[cId] = true;
	if(cId == des)
	{
		if(curDis == dis[des]) //找到一条最短路径
		{
			path_num++;//最短路径数目加1
			if(curTeamsNum > g_max_team_num)
				g_max_team_num = curTeamsNum;
		}
		return;
	}
	if(curDis > dis[des]) //当前的路径长度已经超过最短路径,就没有必要继续搜索了。
		return;	
	//从城市cId开始搜索
	for(int i=0; i<n; i++)
	{
		
		if(!isVisited[i] && road[cId][i] < INF)//如果城市i没有被访问过,且cId到i连通。		
		{
			//isVisited[i] = true;
			dfs(n,i,des,curDis+road[cId][i],curTeamsNum+team_num[i]);
			isVisited[i] = false;
		}

		/*
		//这样的剪枝比上一种更加强大。
		if(dis[cId] + road[cId][i] == dis[i])
			dfs(n,i,des,curDis+road[cId][i],curTeamsNum+team_num[i]);
		*/
	}
}

int main()
{
	int i,j,n,m,c1,c2,L,src,des;

	initData();

	cin>>n>>m>>src>>des;
	for(i=0; i<n; i++)
		cin>>team_num[i];
	for(i=0; i<m; i++)
	{
		cin>>c1>>c2>>L;
		road[c1][c2] = L;
		road[c2][c1] = L;
	}
	
	Dijstra(n,src,des);

	//重置各city的被访问状态。
	for(i=0; i<n; i++)
		isVisited[i] = false;

	dfs(n,src,des,0,team_num[src]);

	cout<<path_num<<" "<<g_max_team_num<<endl;
	return 0;
}

  

posted @ 2012-12-01 09:54  Frank@609  Views(877)  Comments(0Edit  收藏  举报