訓練指南 UVA - 10917(最短路Dijkstra + 基礎DP)
阿新 • • 發佈:2019-02-02
多次 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)