poj 3463 Sightseeing 最短路径数量

题意:

求有向图中最短路和比最短路大1的路径数量。

思路:

需要理解dijkstra算法中dis[n]数组的含义,设cnt[i]表示到点i的最短路径数量,cnt1[i]表示到点i比最短路大1的路径数量。在运行dijkstra算法的过程中每次获得最小dis[i]的时候可以对所有dis[v]+w(v,i)==dis[i]的v做如下更新cnt[i]+=cnt[v],cnt1[i]+=cnt1[v]。而当所有值为某数的dis[i]计算完成时也就是对任意i,dis[i]为同一值且不再变化时,可以对这些满足dis[i]+1=dis[v]+w(v,i)的点i做如下更新:cnt1[i]+=cnt[v];最后结果为cnt[f]+cnt1[f]。

//poj 3463
//sepNINE
#include <iostream>
#include <queue>
using namespace std;
const int maxN=1024;
const int maxM=10024;
int head[maxN];
int head1[maxN];
int dis[maxN];
int cnt[maxN];
int cnt1[maxN];
int n,m,e,e1,s,f;

typedef pair<int,int> pii;
priority_queue<pii,vector<pii>,greater<pii> > q;

struct Edge
{
	int v,w,next;
}edge[maxM],edge1[maxM];
void update(int maxDis)
{
	int i;
	for(int i=1;i<=n;++i){
		if(dis[i]==maxDis){
			for(int e=head1[i];e!=-1;e=edge1[e].next){
				int v=edge1[e].v,w=edge1[e].w;
				if(dis[v]+w==dis[i]+1)
					cnt1[i]+=cnt[v];
			}
		}
	}

}
int dij(int s,int t)
{
	memset(cnt,0,sizeof(cnt));
	memset(cnt1,0,sizeof(cnt1));
	int i,maxDis;
	for(i=1;i<=n;++i)
		dis[i]=INT_MAX;
	dis[s]=0;
	cnt[s]=1;
	maxDis=0;
	q.push(make_pair(dis[s],s));
	while(!q.empty())
	{
		pii u=q.top();q.pop();
		int x=u.second;
		if(u.first>dis[x])
			continue;
		if(maxDis<dis[x]){
			update(maxDis);
			maxDis=dis[x];
		}
		for(int e=head1[x];e!=-1;e=edge1[e].next){
			int v=edge1[e].v,w=edge[e].w;
			if(dis[v]+w==dis[x]){
				cnt[x]+=cnt[v];
				cnt1[x]+=cnt1[v];
			}
		}
		for(int e=head[x];e!=-1;e=edge[e].next)
			if(dis[x]+edge[e].w<dis[edge[e].v]){
				dis[edge[e].v]=dis[x]+edge[e].w;
				q.push(make_pair(dis[edge[e].v],edge[e].v));
			}
	}
	update(maxDis);
	return dis[t];
}

int main()
{
	int cases;
	scanf("%d", &cases);
	while(cases--){
		memset(head,-1,sizeof(head));
		memset(head1,-1,sizeof(head1));
		e=e1=0;
		scanf("%d%d",&n,&m);
		while(m--){
			int a,b,c;
			scanf("%d%d%d",&a,&b,&c);
			edge[e].v=b;edge[e].w=c;edge[e].next=head[a];head[a]=e++;
			edge1[e1].v=a;edge1[e1].w=c;edge1[e1].next=head1[b];head1[b]=e1++;
		}
		scanf("%d%d",&s,&f);
		dij(s,f);
		printf("%d\n",cnt[f]+cnt1[f]);
	}
	return 0;
} 

代码:

时间: 2024-08-04 02:55:35

poj 3463 Sightseeing 最短路径数量的相关文章

poj 3463 Sightseeing(最短路+次短路)

http://poj.org/problem?id=3463 大致题意:给出一个有向图,从起点到终点求出最短路和次短路的条数之和. 解法: 用到的数组:dis[i][0]:i到起点的最短路,dis[i][1]:i到起点的严格次短路 vis[i][0],vis[i][1]:同一维的vis数组,标记距离是否已确定 sum[i][0]:i到起点的最短路条数,sum[i][1]:i到起点的次短路条数 同一维dijkstra,内循环先找出最短的距离(次短路或最短路)d,然后枚举与该点相连的点: if(d

poj 3463 Sightseeing (dij 求最短路和次短路并计数)

dijkstra求最短路和次短路的求法和计算  模板 dijkstra求最短路的变形. 外循环要循环2*n-1次,因为dis[n][2]有2*n个状态,而dis[s][0]已经用过一次. 算法: 1.如果比最短路短就更新最短路和次短路. 2.如果和最短路相等,更新最短路的计数. 3.如果和次短路相等,更新次短路的方法数. 4.如果比次短路短,更新次短路. #include<cstdio> #include<iostream> #include<cstring> #inc

POJ 3463 Sightseeing (最短路 次短路)

Tour operator Your Personal Holiday organises guided bus trips across the Benelux. Every day the bus moves from one city S to another city F. On this way, the tourists in the bus can see the sights alongside the route travelled. Moreover, the bus mak

poj 3463 Sightseeing——次短路计数

题目:http://poj.org/problem?id=3463 当然要给一个点记最短路和次短路的长度和方案. 但往优先队列里放的结构体和vis竟然也要区分0/1,就像把一个点拆成两个点了一样. 不要区分k的fx. #include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; const int N=1005,M=10005; int T

POJ 3463 - Sightseeing

题意:告诉你那n个点以及m条单向边.询问你从s点到e点最短路和比最短路长度大一的路一共有多少条. 思路:dijkstra变形.分别从起点和终点求一边dijkstra.用cnt数组分别记录从起点到达第i个点且长度为最短长度的路径数以及从原点到达第i个点且长度为最短长度的路径数._cnt数组记录到第i个节点的距离为最短距离+1的路径数.注意_cnt[i]所记录的路径只包括第i个节点的pre节点为最短路而pre节点到第i个节点不是最短路的情况.这样可以防止重复计算. 具体的松弛操作:设u为未经过的节点

poj 3463 Sightseeing(次短路+条数统计)

/* 对dij的再一次理解 每个点依旧永久标记 只不过这里多搞一维 0 1 表示最短路还是次短路 然后更新次数相当于原来的两倍 更新的时候搞一下就好了 */ #include<iostream> #include<cstdio> #include<cstring> #include<queue> #include<vector> #define maxn 1010 using namespace std; int T,n,m,num,head[m

(最短路深入)POJ 3463 - Sightseeing

题意: 给一个有向图,计算最短路和比最短路少1的路的条数的和. 分析: 这题真的写死我了. 因为之前很少接触最短路问题,所谓偶尔遇到一次也是套的模板,根本没有细细思考过dijsktra算法.所以栽在了这题上. 这题就是求最短路和次短路. 核心思想在于修改最短路松弛的条件,并且每个节点同时维护最短路和次短路. 很多博主写的很详细,我也不多说了,只是写个博文记录一下自己有多渣,在学习算法的道路上自己真的思考的不够多,也不够努力. 代码: 1 #include <set> 2 #include &l

poj 3259(bellman最短路径)

Wormholes Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 30169   Accepted: 10914 Description While exploring his many farms, Farmer John has discovered a number of amazing wormholes. A wormhole is very peculiar because it is a one-way p

POJ 1637 Sightseeing tour(混合图的欧拉回路)

题目链接 建个图,套个模板. #include <cstdio> #include <cstring> #include <iostream> #include <map> #include <algorithm> #include <vector> #include <string> #include <queue> using namespace std; #define INF 0x3ffffff str