hdu 4725 The Shortest Path in Nya Graph dijkstra 求最短路

32 篇文章 0 订阅

The Shortest Path in Nya Graph

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1279 Accepted Submission(s): 286


Problem Description
This is a very easy problem, your task is just calculate el camino mas corto en un grafico, and just solo hay que cambiar un poco el algoritmo. If you do not understand a word of this paragraph, just move on.
The Nya graph is an undirected graph with "layers". Each node in the graph belongs to a layer, there are N nodes in total.
You can move from any node in layer x to any node in layer x + 1, with cost C, since the roads are bi-directional, moving from layer x + 1 to layer x is also allowed with the same cost.
Besides, there are M extra edges, each connecting a pair of node u and v, with cost w.
Help us calculate the shortest path from node 1 to node N.

Input
The first line has a number T (T <= 20) , indicating the number of test cases.
For each test case, first line has three numbers N, M (0 <= N, M <= 10 5) and C(1 <= C <= 10 3), which is the number of nodes, the number of extra edges and cost of moving between adjacent layers.
The second line has N numbers l i (1 <= l i <= N), which is the layer of i th node belong to.
Then come N lines each with 3 numbers, u, v (1 <= u, v < =N, u <> v) and w (1 <= w <= 10 4), which means there is an extra edge, connecting a pair of node u and v, with cost w.

Output
For test case X, output "Case #X: " first, then output the minimum cost moving from node 1 to node N.
If there are no solutions, output -1.

Sample Input
  
  
2 3 3 3 1 3 2 1 2 1 2 3 1 1 3 3 3 3 3 1 3 2 1 2 2 2 3 2 1 3 4

Sample Output
  
  
Case #1: 2 Case #2: 3
这题 ,就是一个最短路,但是在建图的过程是很难啊,主要是,不同层之间的关系,如果是直接建的话,复杂度,达到n*n,这样是不可接受的,所以,这题主要是拆点,把第0到第i-1层想象成点,这样,我们规过n+2*i为第i层入点,n+2*(i+1)是第i层出点,这样,我们就可以通过原点与这些想象的点想连,就可以在线性时间里,把图建好了!
#include <iostream>
#include <stdio.h>
#include <vector>
#include <string.h>
#include <queue>
using namespace std;
#define typec int
const typec inf =0x4f4f4f4f;
#define E 1000500
#define V 300500
vector<int > vec[V];
typec cost[E],dist[V];
int e,pnt[E],nxt[E],head[V],prev[V],vis[V],num[V];
struct qnode {
    int v;typec c;
    qnode (int vv=0,typec cc=0):v(vv),c(cc){}
    bool operator <(const qnode & r)const {return c>r.c;}
};
void dijkstra(int n,const int src){
    qnode mv;
    int i,j,k,pre;
    priority_queue<qnode> que;
    vis[src]=1;dist[src]=0;
    que.push(qnode(src,0));
    for(pre=src,i=1;i<n;i++){
        for(j=head[pre];j!=-1;j=nxt[j]){
            k=pnt[j];
            if(vis[k]==0&&
               dist[pre]+cost[j]<dist[k]){
                    dist[k]=dist[pre]+cost[j];
                    que.push(qnode(pnt[j],dist[k]));
                    prev[k]=pre;
               }
        }
        while(!que.empty()&&vis[que.top().v]==1){
            que.pop();
        }
        if(que.empty())break;
        mv=que.top();que.pop();
        vis[pre=mv.v]=1;
    }
}
inline void addedge(int u,int v,typec c){
    pnt[e]=v;cost[e]=c;nxt[e]=head[u];head[u]=e++;
}
int main()
{
    int i,u,v,n,m,temp;typec c;
    int tcase,tt=1,s,ee;
    scanf("%d",&tcase);
    while(tcase--){
        scanf("%d%d%d",&n,&m,&c);
        e=0;
        memset(head,-1,sizeof(head));
        memset(vis,0,sizeof(vis));
        memset(prev,-1,sizeof(prev));
        int n3=3*n;
        for(i=0;i<n3;i++)
        vec[i].clear();
        for(i=0;i<n;i++){

            scanf("%d",&temp);
            temp--;
            addedge(n+2*temp+1,i,0);
            addedge(i,n+2*temp,0);
        }
        for(i=0;i<n3;i++)dist[i]=inf;
        for(i=0;i<n-1;i++)
        {
            addedge(n+2*i,n+2*(i+1)+1,c);
            addedge(n+2*(i+1),n+2*i+1,c);
        }
        for(i=0;i<m;i++){
            scanf("%d%d%d",&s,&ee,&c);
            s--,ee--;
            addedge(s,ee,c);
            addedge(ee,s,c);
        }
        dijkstra(n3,0);
        if(dist[n-1]!=inf)
        printf("Case #%d: %d\n",tt++,dist[n-1]);
        else
        printf("Case #%d: -1\n",tt++);
    }

    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值