HLG 1050 Hot Pursuit II【次短路】

题意: 给出一个 有 n 个节点,m 条边的的有向图,求图中的次短路,如果有超过两条以上的最短路,那么次短路的长度即为最短路的长度。

分析: 可以先求出最短路,并保存路径,从 i 到 j 次短路的构成可以用 i 到 点k的次短路加上k 到j 的最短路构成,而i 到 k 的次短路也是通过同样的方法求出,

          因此可以通过枚举不在最短路上的边来依次推出 1 到 2..n 的次短路。

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define INF 0x1f1f1f1f
int g[1003][1003];
int d[1003];
int ord[1003];
int pre[1003];
int sd[1003];
int sl[1003];
int n;
void dijkstra()
{
    int s[1002]={0};
    int i,j,u,tmp;
    d[1]=0;
    pre[1]=-1;
    ord[1]=1;
    for(i=1;i<=n;i++)
    {
        tmp=INF;
        for(j=1;j<=n;j++)
            if(!s[j]&&d[j]<tmp)
            {
                u=j;
                tmp=d[j];
            }
        s[u]=1;
        ord[i]=u;
        for(j=1;j<=n;j++)
            if(d[u]+g[u][j]<d[j])
            {
                d[j]=d[u]+g[u][j];
                pre[j]=u;
            }
    }
}
void sec_dijkstra()
{
    int i,j,tmp;
    for(i=1;i<=n;i++)
    {
        tmp=INF;
        for(j=1;j<=n;j++)
            if(j!=pre[i]&&d[j]+g[j][i]<tmp)
                tmp=d[j]+g[j][i];
        sd[i]=tmp;
    }
}
void cal()
{
    int i;
    sl[1]=sd[1];
    for(i=2;i<=n;i++)
    {
        if(sd[ord[i]]<sl[pre[ord[i]]]+g[pre[ord[i]]][ord[i]])
             sl[ord[i]]=sd[ord[i]];
        else
             sl[ord[i]]=sl[pre[ord[i]]]+g[pre[ord[i]]][ord[i]];
    }
}
int main()
{
    freopen("D:data1.in","r",stdin);
    int i,j,m,a,b,w;
    while(scanf("%d",&n)!=EOF)
    {
        for(i=1;i<=n;i++)
            for(j=1;j<=n;j++)
                g[i][j]=INF;
        for(i=1;i<=n;i++)
        {
            scanf("%d",&m);
            while(m--)
            {
                scanf("%d%d",&b,&w);
                g[i][b]=w;
            }
        }
        for(i=1;i<=n;i++)
            d[i]=INF;
        dijkstra();
        printf("%d ",d[n]);
        sec_dijkstra();
        cal();
        printf("%d\n",sl[n]);
    }
    return 0;
}

 

posted @ 2012-08-06 17:38  'wind  阅读(180)  评论(0编辑  收藏  举报