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;
}
posted @ 2012-12-01 10:24  Frank@609  Views(1396)  Comments(0Edit  收藏  举报