首页 > 代码库 > poj 3463 Sightseeing 最短路径数量

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;	
} 


代码:

poj 3463 Sightseeing 最短路径数量