流水依依

希望朋友们有个好的身体,开开心心工作与学习。

博客园 首页 新随笔 联系 订阅 管理

The Shortest Path in Nya Graph

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)


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 <= 105) and C(1 <= C <= 103), which is the number of nodes, the number of extra edges and cost of moving between adjacent layers.
The second line has N numbers li (1 <= li <= N), which is the layer of ith node belong to.
Then come N lines each with 3 numbers, u, v (1 <= u, v < =N, u <> v) and w (1 <= w <= 104), 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
 

 

Source
 

题目大意:给n个点,m条无向边,边权w,为走这条路的代价。每个点属于某一层,从某层到隔壁层代价都是固定的c,求1到n最短路。

因为每个点可以借助层的属性,到达其他点就有了其他的路径。所以有必要把每层也抽象出额外的点。因为每层的点也是不连通的,就是说如果点i和点j在同一层,并不代表他们之间距离就是0。所以对于层节点,还需要拆点。将每层的点拆成i+n和i + n + n 2个点。i+n表示进入第i层,i+n+n表示从第i层出去。建图的时候如果某点j属于第i层,那么

j—>i + n连一条权为0的边,i + n + n —>j连一条权为0的边。对于层与层之间的关系,因为层抽象出来的点只是一个中间媒介点,所以对于进入第i层的边,只可能通过i+n这个点直接从隔壁层出去,于是i+n—>i +1 + n + n连边,边权c,i + n +1 —>i + n + n连边,边权c。注意虽然第i层被抽象出了i+n和I+ n + n2个点,但他们之间不能连边,因为同一层的点距离不为0,连边了就失去了拆点的意义。

#include <iostream>
#include <stdio.h>
#include <string>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include <math.h>
#include <fstream>
#include <vector>
#include <queue>
#define Min(a,b) ((a)<(b)?(a):(b))
#pragma comment(linker, "/STACK:16777216")
using namespace std ;
typedef __int64 LL ;
const int size=300008 ;
const int inf=2000000000 ;
struct Edge{
   int v ;
   int w ;
   int next ;
};
Edge  edge[size*3] ;
int vec[size] ;
int dist[size] ;
int id ;
int N , M , C;
void init(){
   id=0 ;
   fill(vec,vec+1+3*N,-1) ;
   fill(dist,dist+1+3*N,inf) ;
}
inline void add_edge(int u ,int v ,int w){
     edge[id].v=v ;
     edge[id].w=w ;
     edge[id].next=vec[u] ;
     vec[u]=id++ ;
}
struct Node{
    int id ;
    int dis ;
    Node(){} ;
    Node(int i ,int d):id(i),dis(d){} ;
    friend bool operator <(const Node A ,const Node B){
        return A.dis>B.dis ;
    }
};
int bfs(){
   priority_queue<Node>que ;
   que.push(Node(1,0)) ;
   dist[1]=0 ;
   while(!que.empty()){
       Node now=que.top();
       que.pop() ;
       if(now.id==N)
           return  now.dis ;
       int u=now.id ;
       for(int e=vec[u];e!=-1;e=edge[e].next){
           int v=edge[e].v ;
           int w=edge[e].w ;
           if(now.dis+w<dist[v]){
                dist[v]=now.dis+w ;
                que.push(Node(v,dist[v])) ;
           }
       }
   }
   return -1 ;
}
int getint(){
    char c=getchar();
    int t=0;
    while(c<'0'||c>'9'){
        c=getchar();
    }
    while(c>='0'&&c<='9'){
       t=t*10+c-'0';
       c=getchar();
    }
   return t;
}
int gao(){
   int x ,u ,v ,w;
   N=getint() ;
   M=getint() ;
   C=getint() ;
   init() ;
   for(int i=1;i<=N;i++){
       u=getint() ;
       add_edge(i,u+N,0) ;
       add_edge(u+N+N,i,0) ;
   }
   for(int i=1;i<N;i++){
       add_edge(i+N,i+1+N+N,C) ;
       add_edge(i+1+N,i+N+N,C) ;
   }
   while(M--){
       u=getint() ;
       v=getint() ;
       w=getint() ;
       add_edge(u,v,w) ;
       add_edge(v,u,w) ;
   }
   if(N==0)
      return -1 ;
   if(N==1)
      return 0 ;
   return bfs() ;
}
int main(){
   int T ,k=1;
   cin>>T ;
   while(T--){
       printf("Case #%d: %d\n",k++,gao()) ;
   }
   return 0 ;
}

  

 
posted on 2013-09-13 13:09  流水依依  阅读(231)  评论(0编辑  收藏  举报