UVA 10917 Walk Through the Forest(Dijkstra+DAG动态规划)

题意:gbn最近打算穿过一个森林,但是他比较傲娇,于是他决定只走一些特殊的道路,他打算只沿着满足如下条件的(A,B)道路走:存在一条从B出发回家的路,比所有从A出发回家的路径都短。你的任务是计算一共有多少条不同的回家路径。其中起点的编号为1,终点的编号为2.

思路:首先从终点Dijkstra一次,求出每个点u回家的最短路长度,那么相当于创建了一个新图,当d[B]<d[A]时有一条A指向B的有向边,则题目的目标就是求出起点到终点的路径条数。因为这个图是DAG,可以用动态规划求解。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<vector>
#include<map>
#include<queue>
#include<stack>
#include<string>
#include<map>
#include<set>
#define eps 1e-6
#define LL long long
using namespace std;  

const int maxn = 1000 + 5;
const int INF = 100000000;
int n, m; 

//Dijkstra
struct Edge {
	int from, to, dist;
	Edge(int u = 0, int v = 0, int d = 0) : from(u), to(v), dist(d) {
	}
};
struct HeapNode {         ///用到的优先队列的结点
	int d, u;
	bool operator < (const HeapNode& rhs) const {
		return d > rhs.d;
	}
};
struct Dijkstra {
	int n, m;  //点数和边数
	vector<Edge> edges;  //边列表
	vector<int> G[maxn];   		//每个节点出发的边编号
	bool done[maxn];            //是否已经永久编号
	int d[maxn];                //s到各个点的距离
	int p[maxn];                //最短路中的上一条边
	LL dp[maxn];
	void init(int n) {
		this->n = n;
		for(int i = 0; i < n; i++) G[i].clear();
		edges.clear();
		memset(dp, -1, sizeof(dp));
	}

	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) {            //求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});
				}
			}
		}
	} 

	LL DP(int S) {
		if(S == 1) return 1;
		if(dp[S] != -1) return dp[S];
		else {
			dp[S] = 0;
			int sz = G[S].size();
			for(int i = 0; i < sz; i++) {
				Edge e = edges[G[S][i]];
				if(d[e.to]<d[S]) dp[S] += DP(e.to);
			}
		}
		return dp[S];
	}
} Dij;

void init() {
	Dij.init(n);
	int u, v, d;
	for(int i = 0; i < m; i++) {
		scanf("%d%d%d", &u, &v, &d);
		u--; v--;
		Dij.AddEdge(u, v, d);
		Dij.AddEdge(v, u, d);
	}
	Dij.dijkstra(1);
}

void solve() {
	cout << Dij.DP(0) << endl;
}

int main() {
	//freopen("input.txt", "r", stdin);
	while(scanf("%d%d", &n, &m) == 2 && n) {
		init();
		solve();
	}
	return 0;
}



版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-11-05 01:01:44

UVA 10917 Walk Through the Forest(Dijkstra+DAG动态规划)的相关文章

UVA 10917 - Walk Through the Forest(dijstra)

UVA 10917 - Walk Through the Forest 题目链接 题意:公司编号为1,家编号为2,每次回家都不走回头路,回头路定义为:满足条件的道路(A,B),满足存在一条从B出发比所有从A出发的回家的路径都短,问有几种走法 思路:先从家求dijstra,这样满足条件的道路就是d[A] > d[B],这个图是一个dag,在上面进行dp就可以找出种数了 代码: #include <cstdio> #include <cstring> #include <v

UVA - 10917 Walk Through the Forest (最短路+DP)

题意:Jimmy打算每天沿着一条不同的路走,而且,他只能沿着满足如下条件的道路(A,B):存在一条从B出发回家的路径,比所有从A出发回家的路径都短,你的任务是计算有多少条不同的路径 从后往前找最短路, 对于每一步要更新之后走的位置值: #include<cstdio> #include<cstring> #include<iostream> #include<queue> #include<algorithm> using namespace s

uva 10917 Walk Through the Forest(最短路)

uva 10917 Walk Through the Forest gbn最近打算穿过一个森林,但是他比较傲娇,于是他决定只走一些特殊的道路,他打算只沿着满足如下条件的(A,B)道路走:存在一条从B出发回家的路,比所有从A出发回家的路径都短.你的任务是计算一共有多少条不同的回家路径.其中起点的编号为1,终点的编号为2. Input 多组数据输入,每组数据第一行输入n,m(1<=n<=1000)表示点的数目和边的数目,点的编号为1~n,接下来m行每行输入3个数a,b,c表示有一条双向道路连接a,

HDU 1142 A Walk Through the Forest(dijkstra+记忆化DFS)

题意: 给你一个图,找最短路.但是有个非一般的的条件:如果a,b之间有路,且你选择要走这条路,那么必须保证a到终点的所有路都小于b到终点的一条路.问满足这样的路径条数 有多少,噶呜~~题意是搜了解题报告才明白的Orz....英语渣~ 思路: 1.1为起点,2为终点,因为要走ab路时,必须保证那个条件,所以从终点开始使用单源最短路Dijkstra算法,得到每个点到终点的最短路,保存在dis[]数组中. 2.然后从起点开始深搜每条路,看看满足题意的路径有多少条. 3.这样搜索之后,dp[1]就是从起

HDU 1142 A Walk Through the Forest (Dijkstra + 记忆化搜索 好题)

A Walk Through the Forest Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 6350    Accepted Submission(s): 2332 Problem Description Jimmy experiences a lot of stress at work these days, especial

UVa 10917 A Walk Through the Forest

A Walk Through the Forest Time Limit:1000MS  Memory Limit:65536K Total Submit:48 Accepted:15 Description Jimmy experiences a lot of stress at work these days, especially since his accident made working difficult. To relax after a hard day, he likes t

训练指南 UVA - 10917(最短路Dijkstra + 基础DP)

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出发回家的路径,比

HDU1142 A Walk Through the Forest(dijkstra)

A Walk Through the Forest Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 7733    Accepted Submission(s): 2851 Problem Description Jimmy experiences a lot of stress at work these days, especiall

HDU 1142 A Walk Through the Forest【记忆化搜索+最短路Dijkstra算法】

A Walk Through the Forest Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 7601    Accepted Submission(s): 2796 Problem Description Jimmy experiences a lot of stress at work these days, especial