pku 3255 Roadblocks

This post is written in Chinese. Please consider using Google Translate

这道题不同于一般的次短路径问题,因为允许边重走。看似更为复杂了,其实是更简单了一些。方法为先用Heap+Dijkstra求出1和N的单源最短路径,把无向边看成两个有向边,然后枚举每单向条边(u,v),计算Dist=dis(1,u) + dis(N,v),看看此时Dist的值是否大于dis(1,N),如果是的话用它更新次短路径,保留一个最小的值。

USACO 2006 November Gold

/* 
 * Problem: pku3255 Roadblocks
 * Author: Guo Jiabao
 * Time: 2009.4.14 10:32
 * State: Solved
 * Memo: 次短路径 Dijkstra + Heap (特殊)
*/
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
const int MAXN=5001,MAXM=200001,INF=0x7FFFFFF;
using namespace std;
struct Minheap
{
    struct HeapElement
    {
        int key,value;
    }H[MAXN];
    int size,Position[MAXN];
    void init(){H[size=0].value=-INF;}
    void shift(int key,int value,int pos)
    {
        int i,f;
        HeapElement p={key,value};
        for (i=pos;p.value < H[f=i>>1].value;i=f)
        {
            H[i]=H[f];
            Position[H[i].key]=i;
        }
        H[i]=p;
        Position[H[i].key]=i;
    }
    void ins(int key,int value){shift(key,value,++size);}
    void decrease(int key,int value){shift(key,value,Position[key]);}
    void delmin()
    {
        int i,c;
        HeapElement p=H[size--];
        for (i=1;(c=i<<1)<=size;i=c)
        {
            if (c+1 <=size && H[c+1].value < H[c].value)
                c++;
            if (H[c].value < p.value)
            {
                H[i]=H[c];
                Position[H[i].key]=i;
            }
            else
                break;
        }
        H[i]=p;
        Position[H[i].key]=i;
    }
}H;
struct edge
{
    edge *next;
    int t,c;
}ES[MAXM],*V[MAXN];
int N,M,EC=-1,Shortest,Ans;
int sp[2][MAXN];
inline void addedge(int a,int b,int c)
{
    ES[++EC].next=V[a];
    V[a]=ES+EC; V[a]->t=b; V[a]->c=c;
    ES[++EC].next=V[b];
    V[b]=ES+EC; V[b]->t=a; V[b]->c=c;
}
void init()
{
    int i,a,b,c;
    freopen("block.in","r",stdin);
    freopen("block.out","w",stdout);
    scanf("%d%d",&N,&M);
    for (i=1;i<=M;i++)
    {
        scanf("%d%d%d",&a,&b,&c);
        addedge(a,b,c);
    }
}
void dijkstra(int S,int *sp)
{
    int i,j;
    H.init();
    for (i=1;i<=N;i++)
        H.ins(i,sp[i]=INF);
    H.decrease(S,sp[S]=0);
    for (i=S;;)
    {
        H.delmin();
        for (edge *e=V[i];e;e=e->next)
        {
            j=e->t;
            if (sp[i] + e->c <sp[j])
                H.decrease(j,sp[j]=sp[i] + e->c);
        }
        if (H.size)
            i=H.H[1].key;
        else
            break;
    }
}
void solve()
{
    int i,c;
    dijkstra(1,sp[0]);
    dijkstra(N,sp[1]);
    Shortest=sp[0][N];
    Ans=INF;
    for (i=0;i<=EC;i+=2)
    {
        edge *e1=ES+i,*e2=ES+i+1;
        int a=e1->t,b=e2->t;
        c=sp[0][a] + sp[1][b] + e1->c;
        if (c < Ans && c>Shortest)
            Ans=c;
        c=sp[1][a] + sp[0][b] + e1->c;
        if (c < Ans && c>Shortest)
            Ans=c;
    }
}
int main()
{
    init();
    solve();
    printf("%dn",Ans);
    return 0;
}

Related posts