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++)

        {

            road[i][j] = INF;

            road[j][i] = INF;

        }

    }

}



//单源最短路径算法。

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;



    dis[src] = 0;

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



    cout<<path_num<<" "<<g_max_team_num<<endl;

    return 0;

}

你可能感兴趣的:(merge)