huangriq

导航

poj 3463(最短路、次短路计数)

题意:给出一个有向图、源点、终点,求出源点到终点的最短路径和比最短路径长度大1的路径条数。

思路:求出最短路径条数和次短路径条数,如果次短路比最短路长度大一,返回最短路径和次短路径的条数和。否则返回最短路径条数。

实现:dist[i][2]表示点i到源点的两条路径长度,cnt[i][2]表计数,用dijstra的贪心思想对状态进行更新,与求最短路不同的是,次短路也需要入队和更新。

状态更新如下:

1.新值小于最短路:更新次短路及计数,更新最短路及计数。(先把次短路更新为最短路状态,然后更新最短路)

2.新值等于最短路:更新最短路计数。

3.新值大于最短路,小于次短路:更新次短路及计数。

4新值等于次短路:更新次短路计数。

code

View Code
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
#define M 100010
#define N 1010
#define inf 0x3fffffff
struct edge{
    int to,w,next;
}e[M];
int pre[N],dist[N][2],cnt[N][2],b[N][2];
int cnt0,n,m;
void add(int a,int b,int w)
{
    e[cnt0].next=pre[a];
    e[cnt0].to=b;
    e[cnt0].w=w;
    pre[a]=cnt0++;
}
struct node{
    int w,u,flag;
    bool operator <(const node &x)const
    {
        return w>x.w;
    }
};
int dijstra(int start,int end)
{
    priority_queue<node> q;
    node in;
    for(int i=1;i<=n;i++){
        dist[i][0]=dist[i][1]=inf;
        cnt[i][0]=cnt[i][1]=0;
        b[i][0]=b[i][1]=0;
    }
    dist[start][0]=0;
    cnt[start][0]=1;
    in.w=0;in.u=start;in.flag=0;
    q.push(in);
    while(!q.empty())
    {
        int u=q.top().u;
        int flag=q.top().flag;
        q.pop();
        if(b[u][flag])continue;
        b[u][flag]=1;
        for(int edg=pre[u];edg!=0;edg=e[edg].next)
        {
            int v=e[edg].to;int w=dist[u][flag]+e[edg].w;
            if(dist[v][0]>w)
            {
                if(dist[v][0]!=inf)
                {
                    dist[v][1]=dist[v][0];
                    cnt[v][1]=cnt[v][0];
                    in.w=dist[v][1];
                    in.flag=1;
                    in.u=v;
                    q.push(in);
                }
                dist[v][0]=w;
                cnt[v][0]=cnt[u][flag];
                in.w=dist[v][0];
                in.u=v;
                in.flag=0;
                q.push(in);
            }
            else if(dist[v][0]==w)
            {
                cnt[v][0]+=cnt[u][flag];
            }
            else if(dist[v][1]>w)
            {
                dist[v][1]=w;
                cnt[v][1]=cnt[u][flag];
                in.w=dist[v][1];
                in.flag=1;
                in.u=v;
                q.push(in);
            }
            else if(dist[v][1]==w)
            {
                cnt[v][1]+=cnt[u][flag];
            }
        }
    }
    if(dist[end][0]==dist[end][1]-1)return cnt[end][0]+cnt[end][1];
    else return cnt[end][0];
}
int main()
{
    int ca;
    scanf("%d",&ca);
    while(ca--)
    {
        cnt0=1;
        memset(pre,0,sizeof(pre));
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++)
        {
            int a,b,w;
            scanf("%d%d%d",&a,&b,&w);
            add(a,b,w);
        }
        int start,end;
        scanf("%d%d",&start,&end);
        printf("%d\n",dijstra(start,end));
        //for(int i=1;i<=n;i++)
        //cout<<cnt[i][0]<<":"<<dist[i][0]<<endl;
    }
    return 0;
}

 

posted on 2012-04-24 16:42  huangriq  阅读(544)  评论(0编辑  收藏  举报