1. 程式人生 > >訓練指南 UVA - 10917(最短路Dijkstra + 基礎DP)

訓練指南 UVA - 10917(最短路Dijkstra + 基礎DP)

多次 i++ 記憶化 上一條 是否 而且 false 點列 type


layout: post
title: 訓練指南 UVA - 10917(最短路Dijkstra + 基礎DP)
author: "luowentaoaa"
catalog: true
mathjax: true
tags:
- 最短路
- 基礎DP
- Dijkstra
- 圖論
- 訓練指南


Walk Through the Forest UVA - 10917

題意

Jimmy打算每天沿著一條不同的路走,而且,他只能沿著滿足如下條件的道路(A,B):存在一條從B出發回家的路徑,比所以從A出發回家的路徑都短,你的任務是計算有多少條不同的路徑

題意

題意就轉化成如果終點到i 比到j的路勁短,就連線,然後記憶化搜索就行(這幾天這種題做太多次了)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=998244353;
const int maxn=1050;
const ll inf=0x3f3f3f3f3f3f3f3fLL;
struct Edge{
    int from,to,dist;
};
struct HeapNode{
    int d,u;
    bool operator <(const HeapNode& rhs)const{
        return d>rhs.d;
    }
};
struct Dijkstra{
    int n,m;              ///點數和邊數  點編號0~N-1
    vector<Edge>edges;    ///邊列表
    vector<int>G[maxn];   ///每個節點出發的邊編號
    bool done[maxn];      /// 是否已永久標號
    int d[maxn];          /// s到各個點的距離
    int p[maxn];          /// 最短路中的上一條邊

    void init(int n){
        this->n=n;
        for(int i=0;i<n;i++)G[i].clear();
        edges.clear();
    }
    void AddEdge(int from,int to,int dist){ ///無向圖調用兩次
        edges.push_back((Edge){from,to,dist});
        m=edges.size();
        G[from].push_back(m-1);
    }
    void dijkstra(int s){
        priority_queue<HeapNode>Q;
        for(int i=0;i<n;i++)d[i]=inf;
        d[s]=0;
        memset(done,0,sizeof(done));
        Q.push((HeapNode){0,s});
        while(!Q.empty()){
            HeapNode x=Q.top();Q.pop();
            int u=x.u;
            if(done[u])continue;
            done[u]=true;
            for(int i=0;i<G[u].size();i++){
                Edge& e=edges[G[u][i]];
                if(d[e.to]>d[u]+e.dist){
                    d[e.to]=d[u]+e.dist;
                    p[e.to]=G[u][i];
                    Q.push((HeapNode){d[e.to],e.to});
                }
            }
        }
    }
    /// dist[i]為s到i的距離,paths[i]為s到i的最短路徑(經過的結點列表,包括s和t)
    void GetShortestPaths(int s,int* dist,vector<int>* paths){///paths是二維鏈表
        dijkstra(s);
        for(int i=0;i<n;i++){
            dist[i]=d[i];
            paths[i].clear();
            int t=i;
            paths[i].push_back(t);
            while(t!=s){
                paths[i].push_back(edges[p[t]].from);
                t=edges[p[t]].from;
            }
            reverse(paths[i].begin(),paths[i].end());
        }
    }
};

Dijkstra solver;
int d[maxn];
int dp(int u){
    if(u==1)return 1;
    int &ans=d[u];
    if(ans>=0)return ans;
    ans=0;
    for(int i=0;i<solver.G[u].size();i++){
        int v=solver.edges[solver.G[u][i]].to;
        if(solver.d[v]<solver.d[u])ans+=dp(v);
    }
    return ans;
}
int main()
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    std::cout.tie(0);
    int n,m;
    while(cin>>n){
        if(n==0)break;
        cin>>m;
        solver.init(n);
        for(int i=0;i<m;i++){
            int a,b,c;
            cin>>a>>b>>c;a--;b--;
            solver.AddEdge(a,b,c);
            solver.AddEdge(b,a,c);
        }
        solver.dijkstra(1);
        memset(d,-1,sizeof(d));
        cout<<dp(0)<<endl;
    }
    return 0;
}

訓練指南 UVA - 10917(最短路Dijkstra + 基礎DP)