HDU 4725-J - The Shortest Path in Nya Graph-增点建图-层次网络-最短路

与hdu5521类似的层次网络最短路问题

http://acm.hdu.edu.cn/showproblem.php?pid=4725

题意是给 n个点,m个边,C

m条边u,v,w,w是边权

 除此之外给你一个个 layer[i],表示点i属于第 layer[i]层! 


关于层的性质有两个 【如果相邻两层都存在节点,则x层任意节点可以与x+1层任意节点互通,代价为C】

当然如果有一层为空,则空层是无法与上下层相通的哦!相当于断层!


建图方法和hdu5521一致,增一个点代表一层,不同的是,5521是【每一层的所有点互通】,而本题只要求相邻层互通,

注意:【层之内是不允许互通的】

因此建图需要注意 不能直接 【把新new的点 与层内的所有点直接建立双向边

应该 

A   【建立 该层内的节点 指向 当前层的新new的虚拟节点的单向边】【权值为0】

B、【第i层的虚拟节点指向 i+1层的所有node】【权值为C】

C、【第i+1层的虚拟节点指向 i层的所有node】【权值为C】

【这样就能确保符合题意,两层内任意节点互通,但同层节点不连通


dji:561ms

#include <iostream>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
struct node
{
    int x;
    int v;
    node() {}
    node(int a,int b)
    {
        x=a,v=b;
    }
    bool operator <(const node&b) const
    {
        return v>b.v;
    }
};
vector<node >mp[200005];
vector <int >layer[200005];
int idx;

int vis[200005];
priority_queue<node> q;
int dis[200005];
const int inf=1e9;

int main()
{
    int cnt=1;
    void dji();
    int t;
    cin>>t;
    while(t--)
    {
        int n,m,c;
        int i,j;
        cin>>n>>m>>c;
        int x,y,v;
        for (i=1; i<=n*2; i++) mp[i].clear();
        for (i=1;i<=n*2;i++)
        layer[i].clear();

        for (i=1; i<=n; i++)
        {
            scanf("%d",&x);
            layer[x].push_back(i);
        }
        for (i=1; i<=m; i++)
        {
            scanf("%d%d%d",&x,&y,&v);
            mp[x].push_back(node(y,v));
            mp[y].push_back(node(x,v));
        }
        idx=n;
        for (i=1; i<=n; i++)
        {
            idx++;
            if (layer[i].size()==0) continue;

            for (j=0; j<layer[i].size(); j++)
            {
                  v=layer[i][j];
            //mp[idx].push_back(node(v,0));原先的错误建图法
                mp[v].push_back(node(idx,0));
            }
        }
        for (i=n+1; i<idx; i++)
        {
            if (layer[i-n].size()==0||layer[i-n+1].size()==0) continue;
            mp[i].push_back(node(i+1,c));
             for (j=0; j<layer[i-n].size(); j++)//更正后的建图法
            {
                  v=layer[i-n][j];
                mp[i+1].push_back(node(v,c));   //i+1-n层的虚拟节点指向i-n层的node
            }
             for (j=0; j<layer[i-n+1].size(); j++)//更正后的建图法
            {
                  v=layer[i-n+1][j];
                mp[i].push_back(node(v,c));//i-n层的虚拟节点指向下一层的node
            }
        }
        dji();
        printf("Case #%d: ",cnt++);
        if (dis[n]==inf) printf("-1\n");
        else
        printf("%d\n",dis[n]);

    }
    return 0;
}
void dji()
{
    while(!q.empty())q.pop();
    int i;
    for (i=1;i<=idx;i++)
    {
        dis[i]=inf;
        vis[i]=0;
    }
    dis[1]=0;
    node st(1,0);
    q.push(st);
    while(!q.empty())
    {
        node t=q.top();
        q.pop();
        int num=t.x;
        if (vis[num])continue;
        vis[num]=1;
        for (i=0;i<mp[num].size();i++)
        {
            node tmp=mp[num][i];
            int x=tmp.x;
            int v=tmp.v;
            if (!vis[x]&&v+dis[num]<dis[x])
            {
                dis[x]=v+dis[num];
                q.push(node(x,dis[x]));
            }
        }
    }


}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值