算法提高课-图论-单源最短路的综合应用-AcWing 342. 道路与航线:最短路dijkstra、拓扑排序 、综合题、好题
生活随笔
收集整理的這篇文章主要介紹了
算法提高课-图论-单源最短路的综合应用-AcWing 342. 道路与航线:最短路dijkstra、拓扑排序 、综合题、好题
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
題目分析
來(lái)源:acwing
分析:
道路:雙向,邊權(quán)非負(fù),
航線:單向,邊權(quán)可正可負(fù),且無(wú)環(huán)。
根據(jù)題意,點(diǎn)可以分為很多團(tuán)(連通塊),團(tuán)內(nèi)部只有道路(道路是雙向的,而且是連通的,所以不能存在航線,否則有環(huán),矛盾);而航線是在團(tuán)與團(tuán)之間。航向滿足什么呢? 團(tuán)與團(tuán)之間的航線也是無(wú)環(huán)的,是滿足拓?fù)湫虻摹K?#xff0c;團(tuán)與團(tuán)之間是有向無(wú)環(huán)圖。
本題:
思路是:先把每個(gè)團(tuán)看成1個(gè)點(diǎn),用拓?fù)湫驋呙鑱?lái)處理;然后對(duì)于每個(gè)團(tuán),內(nèi)部使用dijkstra算。
id[]:存儲(chǔ)每個(gè)點(diǎn)屬于哪個(gè)連通塊;
vector< int> block[]:存儲(chǔ)每個(gè)連通塊里有哪些點(diǎn)
如果id[ver] == id[j],如果j能被更新,則把j插入到堆中;
如果id[ver] != id[j],則將id[j] 這個(gè)連通塊的入度-1,如果減到0,則將其插入到拓?fù)渑判虻年?duì)列中。
ac代碼
#include<bits/stdc++.h> #define x first #define y second using namespace std; typedef pair<int,int> PII; const int N = 25010, M = 150010; const int INF = 0x3f3f3f3f; int n, mr, mp, S; int h[N],e[M],w[M],ne[M],idx; int id[N]; //每個(gè)點(diǎn)屬于哪個(gè)連通塊 vector<int> block[N]; // 每個(gè)連通塊中有哪些點(diǎn) int bcnt; // 連通塊的個(gè)數(shù) int dist[N]; bool st[N]; int din[N];// 每個(gè)連通塊的入度queue<int> q;void add(int a, int b, int c){e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++; }// 把連通的點(diǎn)放到連通塊中 void dfs(int u, int bid){id[u] = bid; // u這點(diǎn)放到bid這個(gè)block中block[bid].push_back(u);// 遍歷連通的所有臨邊for(int i = h[u]; ~i; i = ne[i]){int j = e[i];if(!id[j]) dfs(j, bid); // 都放到bid這個(gè)連通塊中}}// 求每個(gè)連通塊內(nèi)部的最短路 void dijkstra(int bid){priority_queue<PII, vector<PII>, greater<PII>> heap;for(auto ver : block[bid]) heap.push({dist[ver],ver});while(heap.size()){auto t = heap.top();heap.pop();int ver = t.y, distance = t.x;if(st[ver]) continue;st[ver] = true;for(int i = h[ver]; ~i; i = ne[i]){int j = e[i];if(dist[j] > dist[ver] + w[i]){dist[j] = dist[ver] + w[i];if(id[j] == id[ver]) heap.push({dist[j], j});}if(id[j] != id[ver] && -- din[id[j]] == 0)q.push(id[j]);}} }void topsort(){memset(dist, 0x3f, sizeof dist);dist[S] = 0;for(int i = 1; i <= bcnt; i ++){if(!din[i])q.push(i); // 把入度為零的連通塊加入隊(duì)列中}while(q.size()){int t = q.front();q.pop();dijkstra(t); //對(duì)編號(hào)為t的連通塊進(jìn)行dijkstra}}int main(){cin >> n >> mr >> mp >> S;memset(h, -1, sizeof h);while(mr --){int a, b, c;scanf("%d%d%d", &a, &b, &c);add(a, b, c), add(b, a, c);}// 所有的點(diǎn)分類到不同的連通塊// 放在id[]數(shù)組中for(int i = 1; i <= n; i ++){if(!id[i])dfs(i, ++ bcnt); }// 讀入航線while(mp --){int a, b, c;scanf("%d%d%d",&a, &b, &c);add(a, b, c);din[id[b]] ++; // 后者所在連通塊的入度+1}topsort();for(int i = 1; i <= n; i ++)if(dist[i] > INF/ 2) puts("NO PATH");else printf("%d\n", dist[i]); }題目來(lái)源
https://www.acwing.com/problem/content/344/
總結(jié)
以上是生活随笔為你收集整理的算法提高课-图论-单源最短路的综合应用-AcWing 342. 道路与航线:最短路dijkstra、拓扑排序 、综合题、好题的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 算法提高课-图论-单源最短路的综合应用-
- 下一篇: 算法提高课-数学知识-矩阵乘法-AcWi