HDU 4725 The Shortest Path in Nya Graph(最短路拆点)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4725

题意:n个点,某个点属于某一层。共有n层。第i层的点到第i+1层的点和到第i-1层的点的代价均是C。另外有一类边连接两个点u、v,代价w。求1到n的最短路。

思路:拆点。n个点不动,编号1到n。将n层每层拆成两个点,第i层拆成n+i*2-1,n+i*2。相邻的层连边(n+i*2-1,n+(i+1)*2,C),(n+(i+1)*2-1,n+i*2,C)。若顶点u属于第i层,连边(u,n+i*2-1,0),(n+i*2,u,0)。再加上另外的那种边。最后用优先队列跑最短路。

 

vector<pair<int,int> > g[N];

int a[N];

int f[N],n,m,C;



struct node

{

    int u,cost;



    node(){}

    node(int _u,int _cost)

    {

        u=_u;

        cost=_cost;

    }



    int operator<(const node &a) const

    {

        return cost>a.cost;

    }

};



int cal()

{

    priority_queue<node> Q;

    Q.push(node(1,0));

    int i;

    FOR1(i,n*3) f[i]=INF;

    f[1]=0;

    while(!Q.empty())

    {

        int u=Q.top().u;

        Q.pop();



        if(u==n) return f[u];



        FOR0(i,SZ(g[u]))

        {

            int v=g[u][i].first;

            int w=g[u][i].second;

            if(f[u]+w<f[v])

            {

                f[v]=f[u]+w;

                Q.push(node(v,f[v]));

            }

        }

    }

    return -1;

}



void add(int u,int v,int w)

{

    g[u].pb(MP(v,w));

}



int main()

{

    int num=0;

    rush()

    {

        RD(n,m,C);

        int i;

        FOR1(i,n*3) g[i].clear();

        FOR1(i,n-1)

        {

            add(n+i*2-1,n+(i+1)*2,C);

            add(n+(i+1)*2-1,n+i*2,C);

        }

        FOR1(i,n)

        {

            RD(a[i]);

            add(i,n+a[i]*2-1,0);

            add(n+a[i]*2,i,0);

        }

        FOR1(i,m)

        {

            int u,v,w;

            RD(u,v,w);

            add(u,v,w);

            add(v,u,w);

        }

        int ans=cal();

        printf("Case #%d: %d\n",++num,ans);

    }

}

  

 

你可能感兴趣的:(Graph)