您的位置:首页 > 其它

POJ 3463 Sightseeing

2009-12-29 17:12 190 查看
POJ 3463 Sightseeing
题目大意:旅行团每天固定的从S地出发到达T地,为了省油要求尽量走最短路径或比最短路径长1单位距离的路径,求满足条件的路径条数
分析:根据描述可知,本题的要求就是要求出最短路和比最短路长1的次短路,因此可用Dijkstra来解决。具体做法如下:用两组数分别记录最短路和次短路的长度(dist),条数(cnt),访问标记(used),建一个优先队列,元素单位包括节点序号(v),该节点路经长(len),以及记录路径类型(ref),每次从优先队列中取出有效节点后,用它所记录的路径长更新待比较路径,分别用它和当前所记录的该节点的最短路径以及此段路径比较,满足更新条件则记录路径类型,并生成新节点加入优先队列,同时更新当前节点处该类型路径条数。如果不满足条件但是满足相等关系,则添加相应的条数到该节点所记录的路径条数上。
代码及其思想借鉴了此处:http://www.cnblogs.com/zhangjinglei/archive/2009/07/31/1536160.html
#include<stdio.h>
#include<memory.h>
#include<queue>
using namespace std;
#define N 1001
#define M 10001
#define INF 0x7fffffff
#define clear(a) memset(a,0,sizeof(a))
struct Edge
{
int v;
int len;
int ref;
Edge *link;
Edge new_E(int v1,int l,int r){v=v1,len=l,ref=r;return *this;}
}*E
,mempool[M];
int dist
[2],used
[2],cnt
[2];
int n,m,memh,S,T;
void AddEdge(int u,int v,int len)
{
Edge *e=&mempool[memh++];
e->v=v;
e->len=len;
e->link=E[u];
E[u]=e;
}
bool operator <(Edge a,Edge b)
{
return a.len>b.len;
}
priority_queue<Edge,vector<Edge> >Q;
void InitData()
{
int i,u,v,len;
memh=0;
scanf("%d%d",&n,&m);
clear(E);
for(i=1;i<=m;i++){
scanf("%d%d%d",&u,&v,&len);
AddEdge(u,v,len);
}
scanf("%d%d",&S,&T);
}
int Dijstra()
{
Edge D,P;
clear(cnt);
clear(used);
for(int i=1;i<=n;i++)
dist[i][0]=dist[i][1]=INF;
dist[S][0]=0;
cnt[S][0]=1;
while(!Q.empty()) Q.pop();
Q.push(D.new_E(S,0,0));
while(!Q.empty()){
P=Q.top();
Q.pop();
if(!used[P.v][P.ref]){
used[P.v][P.ref]=1;
for(Edge *e=E[P.v];e;e=e->link){
int tmp=P.len+e->len;
if(tmp<dist[e->v][0]){
if(dist[e->v][0]!=INF){
dist[e->v][1]=dist[e->v][0];
cnt[e->v][1]=cnt[e->v][0];
Q.push(D.new_E(e->v,dist[e->v][0],1));
}
dist[e->v][0]=tmp;
cnt[e->v][0]=cnt[P.v][P.ref];
Q.push(D.new_E(e->v,tmp,0));
}
else if(tmp==dist[e->v][0]){
cnt[e->v][0]+=cnt[P.v][P.ref];
}
else if(tmp<dist[e->v][1]){
dist[e->v][1]=tmp;
cnt[e->v][1]=cnt[P.v][P.ref];
Q.push(D.new_E(e->v,tmp,1));
}
else if(dist[e->v][1]==tmp){
cnt[e->v][1]+=cnt[P.v][P.ref];
}
}
}
}
if(dist[T][1]-1==dist[T][0])
cnt[T][0]+=cnt[T][1];
return cnt[T][0];
}
int main()
{
int cs;
freopen("data.txt","r",stdin);
for(scanf("%d",&cs);cs;cs--){
InitData();
printf("%d/n",Dijstra());
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: