您的位置:首页 > 其它

ACM POJ 3463 Sightseeing

2010-08-05 16:15 267 查看
题目大意:求源点S到终点T的最短路的数量和比最短路长1的数量。

解题思路:我们可以利用dijstra算法的思想,只需在其中进行一些改进即可。可以先定义一个二维的数组dist
[2]。dist[i][0]代表源点S到点i的最短路,dist[i][1]代表源点S到点i的次短路。初始化dist[S][0]=0,其余的都初始化为无穷大。然后定义一个二维数组waynum
[2]记录路径方法数,waynum[S][0]=1,其余初始为0。再定义一个标记数组vis
[2],初始vis[S][0]被标记已访问,其余未访问。采用dijstra算法的思想,每次从dist
[2]中选择一个未被标记且值最小的点dist[v][flag](可能这个值是这个点的最短路,也可能是次短路,只有当此点的最短路被标记了次才可能选中此点的次短路)。再用这个值val去更新此点的邻接点u。更新的方法如下:

(1)如果val小于dist[u][0],则dist[u][1]=dist[u][0],waynum[u][1]=waynum[u][0],dist[u][0]=val.waynum[u][0]=waynum[v][flag]。否则转(2)

(2)如果val等于dist[u][0],则waynum[u][0]+=waynum[v][flag];否则转(3)

(3)如果val小于dist[u][1],则dist[u][1]=val.waynum[u][1]=waynum[v][flag]。

否则转(4)

(4)如果val等于dist[u][1],则waynum[u][1]+=waynum[v][flag].否则什么都不做。

这样循环计算2*n-1次就可以计算出源点到所有点的最短路和次短路的方法数了,而对于终点T,如果次短路比最短路大1则答案为最短路和次短路的方法数之和,否则就为最短路的方法数。



#include<iostream>
usingnamespacestd;
#defineINF1000100101
#definemaxn1010
#definemaxm11000
structEdge{
intv,val,next;
}e[maxm];
intbox[maxn];
intn,m,S,T;
intdis[maxn][2],dp[maxn][2],used[maxn][2];
intdij()
{
inti,j;
memset(used,0,sizeof(used));
memset(dp,0,sizeof(dp));
for(i=1;i<=n;i++)
dis[i][0]=dis[i][1]=INF;
dis[S][0]=0;
dp[S][0]=1;
for(i=1;i<n*2;i++)
{
intmn=INF,x,flag;
for(j=1;j<=n;j++)
{
if(!used[j][0]&&mn>dis[j][0])
{
mn=dis[j][0];
x=j;
flag=0;
}
elseif(!used[j][1]&&mn>dis[j][1])
{
mn=dis[j][1];
x=j;
flag=1;
}
}
if(mn==INF)break;
used[x][flag]=1;
inty,val;
for(j=box[x];j!=-1;j=e[j].next)
{
y=e[j].v;
val=e[j].val;
if(mn+val<dis[y][0])
{
dis[y][1]=dis[y][0];
dp[y][1]=dp[y][0];
dis[y][0]=mn+val;
dp[y][0]=dp[x][flag];
}
elseif(mn+val==dis[y][0])
{
dp[y][0]+=dp[x][flag];
}
elseif(mn+val<dis[y][1])
{
dis[y][1]=mn+val;
dp[y][1]=dp[x][flag];
}
elseif(mn+val==dis[y][1])
{
dp[y][1]+=dp[x][flag];
}
}
}
if(dis[T][0]+1==dis[T][1])
returndp[T][0]+dp[T][1];
returndp[T][0];
}
intmain()
{
inti,j,x,y,val,cas;
scanf("%d",&cas);
while(cas--)
{
scanf("%d%d",&n,&m);
memset(box,-1,sizeof(box));
for(i=1;i<=m;i++)
{
scanf("%d%d%d",&x,&y,&val);
e[i].v=y;
e[i].val=val;
e[i].next=box[x];
box[x]=i;
}
scanf("%d%d",&S,&T);
printf("%d/n",dij());
}
return0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: