1. 程式人生 > >[ARC061E]すぬけ君の地下鉄旅行 / Snuke's Subway Trip

[ARC061E]すぬけ君の地下鉄旅行 / Snuke's Subway Trip

地鐵 出口 lis color bottom rom void bsp har

題目大意:Snuke的城鎮有地鐵行駛,地鐵線路圖包括$N$個站點和$M$個地鐵線。站點被從$1$到$N$的整數所標記,每條線路被一個公司所擁有,並且每個公司用彼此不同的整數來表示。

第$i$條線路($1\le i \le M$)是直接連接$p_i$與$q_i$的雙向鐵路,中間不存在其他站點,且這條鐵路由$c_i$公司所擁有。

如果乘客只乘坐同一公司的鐵路,他只需要花費一元,但如果更換其他公司的鐵路需要再花一元。當然,如果你要再換回原來的公司,你還是要花一元。

Snuke在1號站的位置出發,他想通過地鐵去第$N$站,請求出最小錢數。如果無法到達第$N$站,輸出-1。

最短路建圖的好題
首先我們知道,在同一個顏色的聯通塊內只要一塊錢就可以隨意走動

那麽我們就在這個聯通塊的入口處連一條長度為1的邊,中間連長度為0的邊
用map存每個顏色的入口聯通塊的編號,可知最多有M*2種編號
跑一遍最短路即可,註意答案要除以2(入口和出口都經過了一遍)
代碼:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<queue>
 5 #include<map>
 6 #define M 1000010
 7 using namespace std;
 8 int read()
 9 {
10     char
ch=getchar();int x=0; 11 while(ch>9||ch<0) ch=getchar(); 12 while(ch>=0&&ch<=9) x=x*10+ch-0,ch=getchar(); 13 return x; 14 } 15 struct point{ 16 int to,next,dis; 17 }e[M<<1]; 18 int n,m,num,cnt; 19 int head[M],dis[M];bool vis[M]; 20 void add(int
from,int to,int dis) 21 { 22 e[++num].next=head[from]; 23 e[num].to=to; 24 e[num].dis=dis; 25 head[from]=num; 26 } 27 void SPFA() 28 { 29 memset(dis,127,sizeof(dis)); 30 queue<int>q; 31 q.push(1); 32 vis[1]=true; 33 dis[1]=0; 34 while(!q.empty()) 35 { 36 int x=q.front(); q.pop(); 37 for(int i=head[x];i;i=e[i].next) 38 { 39 int to=e[i].to; 40 if(dis[to]>dis[x]+e[i].dis) 41 { 42 dis[to]=dis[x]+e[i].dis; 43 if(!vis[to]) 44 { 45 vis[to]=true; 46 q.push(to); 47 } 48 } 49 } 50 vis[x]=false; 51 } 52 } 53 map<pair<int,int>,int>P; 54 int get(int x,int y) 55 { 56 if(P.find(make_pair(x,y))!=P.end()) return P[make_pair(x,y)]; 57 else return P[make_pair(x,y)]=++cnt; 58 } 59 int main() 60 { 61 n=cnt=read(); m=read(); 62 for(int i=1;i<=m;i++) 63 { 64 int a=read(),b=read(),c=read(); 65 int id1=get(a,c),id2=get(b,c); 66 add(id1,id2,0); add(id2,id1,0); 67 add(a,id1,1); add(id1,a,1); 68 add(b,id2,1); add(id2,b,1); 69 } 70 SPFA(); 71 printf("%d\n",dis[n]>2*n?-1:dis[n]/2); 72 return 0; 73 }

[ARC061E]すぬけ君の地下鉄旅行 / Snuke's Subway Trip