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;

}

  

你可能感兴趣的:(merge)