UVA10917 Walk Through the Forest(最短路径树)

题目大意:
给你m条边与n个点
终点是点2,起点是点1
当(A,B)中A到终点的最短路径大于B到终点的最短路径的时候你才可以走这两个点
问你有多少条路径可以从起点走到终点

思路:
就是从终点向其他所有点延伸
找2到其他所有点的最短路径
这样就形成了一个最短路径树
我们设一个数组表示每个点能走到起点的路径种类
(方便记忆化搜素)
把起点的值设为1
然后从点2开始按题目给的要求我们向上倒着走
最后把数组中点2的值给他加上就好了

AC代码:

#include <bits/stdc++.h>
using namespace std;
vector<pair<int,int>>e[1010];
int d[1010];
int path[1010];
void dij(int st)
{
    priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>>>q;//小顶堆
    memset(d,0x3f3f,sizeof(d));
    int vis[1010]= {0};
    q.push({0,st});
    d[st]=0;
    while(!q.empty())
    {
        int x=q.top().second;//这里跟vector不一样是second因为这里用小顶堆优先看前面的边长
        q.pop();
        if(vis[x])continue;
        vis[x]=1;
        for(int i=0; i<e[x].size(); i++)
        {
            int y=e[x][i].first;
            int w=e[x][i].second;
            if(d[y]>d[x]+w)
            {
                d[y]=d[x]+w;
                q.push({d[y],y});
            }
        }
    }
    return;
}
int dfs(int x)
{
    if(path[x]!=-1)return path[x];//记忆化搜素
    path[x]=0;
    for(int i=0; i<e[x].size(); i++)
    {
        int y=e[x][i].first;
        if(d[x]<d[y])
        {
            path[x]+=dfs(y);//往上找起点
        }
    }
    return path[x];
}
int main()
{
    int n,m;
    while(cin>>n)
    {
        if(n==0)break;
        cin>>m;
        memset(path,-1,sizeof(path));
        path[1]=1;
        for(int i=1; i<=n; i++)e[i].clear();
        for(int i=0; i<m; i++)
        {
            int a,b,w;
            cin>>a>>b>>w;
            e[a].push_back(make_pair(b,w));
            e[b].push_back(make_pair(a,w));
        }
        dij(2);
        int ans=dfs(2);
        cout<<ans<<endl;
    }
    return 0;
}

上一篇:linux命令集(监测程序)


下一篇:Mac下如何使用gmt