最短路(遍历边)计蒜客—DD坐地铁
題目:
C 城有 n 個站點, m 條雙向地鐵,每條地鐵有一個 companyicompany_icompanyi?表示它的公司,如果連續乘坐同一家公司的地鐵只要花 1元錢就好。DD現在想出門找薩摩耶玩,但是 DD 是貧困人口, 她想知道最少花費多少錢能從 1 號點前往 n 號點
輸入格式
第一行兩個整數分別表示 n,m
接下來 m 行每行 3 個整數,分別表示地鐵的起點終點和公司
輸出格式
輸出 DD 的最少花費是多少
數據范圍
對于 30%30\%30% 的數據, n≤100,c≤100n \leq 100,c \leq 100n≤100,c≤100
對于另外 20%20\%20% 的數據, n≤105,c≤1n \leq 10^5,c \leq 1n≤105,c≤1對于 100%100\%100% 的數據, n,c≤105,m≤2×105n,c \leq 10^5,m \leq 2 \times 10^5n,c≤105,m≤2×105輸出時每行末尾的多余空格,不影響答案正確性
樣例輸入
8 11
1 3 1
1 4 2
2 3 1
2 5 1
3 4 3
3 6 3
3 7 3
4 8 4
5 6 1
6 7 5
7 8 5
樣例輸出
2
分析:
本人小菜菜一枚,計蒜客面試題,這道我搞了三四個小時沒搞出來,最后大佬出手,就知有木有哈,竟然是走邊,orz%%%%%%%%,下面來分析哈。
1.首先看數據范圍,就知道開二維數組是不得行的(除了用容器 map,vector啥的),那么這里就用鄰接表,記錄每一條邊和點,順便由邊(tot),可以直接記錄這個邊上是哪家公司的車車在跑;
2.接著用優先隊列建一個小根堆,里面的兩個數據分別為x:與1號點連通的x號點;y:1~x點間交換過多少次公司;
3.因為建的是小根堆,每次拿出棧頂的是最小交換公司次數,所以每次存在一個與1不連通的點,進隊列都更新次數,直到到達n號點。
AC代碼:
#include <bits/stdc++.h> using namespace std; typedef long long ll;const int N=1e5+10; const int M=4e5+10;int n,m; int tot,fir[N]; int nex[M],to[M],id[M]; void add(int x,int y,int z){++tot;to[tot]=y; id[tot]=z;nex[tot]=fir[x]; fir[x]=tot; }bool vis[M]; int dis[M]; struct node{int x,y;/**node(){}node(int x,int y):x(x),y(y){}*/bool operator<(const node&a)const{return y>a.y;} }; priority_queue<node> Q;int dij(int sr){memset(vis,0,sizeof(vis));memset(dis,0x3f,sizeof(dis));while(!Q.empty()) Q.pop();for(int i=fir[sr]; i; i=nex[i]){dis[i]=1;Q.push((node){i,1});//Q.push(node(i,1));}while(!Q.empty()){int d=Q.top().x;Q.pop();if(vis[d]) continue;vis[d]=1;int u=to[d];if(u==n) return dis[d];for(int i=fir[u]; i; i=nex[i]){int t=(id[i]==id[d])?0:1;if(!vis[i] && dis[i]>dis[d]+t){dis[i]=dis[d]+t;Q.push((node){i,dis[i]});// Q.push(node(i,dis[i]));}}}return -1; }int main() {scanf("%d%d",&n,&m);for(int i=0; i<m; ++i){int t1,t2,t3;scanf("%d%d%d",&t1,&t2,&t3);add(t1,t2,t3); add(t2,t1,t3);}int ans=dij(1);printf("%d\n",ans);return 0; }總結
以上是生活随笔為你收集整理的最短路(遍历边)计蒜客—DD坐地铁的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 减肥能吃水煮花生吗
- 下一篇: 线段树维护区间最大值+第 45 届(IC