1. 程式人生 > >2017 ACM-ICPC 亞洲區(烏魯木齊賽區)網絡賽 H. Skiing

2017 ACM-ICPC 亞洲區(烏魯木齊賽區)網絡賽 H. Skiing

pre 亞洲 oid ons bool cal nbsp 拓撲排序 air

題意:在這個寒假中,鮑勃有計劃在山區度假勝地滑雪。這個滑雪勝地有M個不同的滑雪道和N個不同的標誌位於那些轉彎處點。從第S標記到第T標誌的第i路徑具有長度L。每個路徑必須遵循降低高度的原則,起點必須嚴格高於終點。 現在,你應該幫助鮑勃找到最長的滑雪道。

思路:因為說起點必須嚴格高於終點,所以是一個有向圖,而且不可能存在環,可以看作是一個DAG模型, 求DAG上的最長路可以用dp來求,有些時候也可以看作AOE網,這樣就可以用拓撲排序來求關鍵路徑來解決了;

代碼:

#include<algorithm>

#include<iostream>

#include
<cstring> #include<cstdio> #include<queue> using namespace std; #define MP make_pair const int N = 100000 + 10; const int INF = 0x3f3f3f3f; vector<pair<int, int> > edge[N]; class Topological{ private: int tot = 0, vis[N], n; queue
<int> Q; public: int in[N], dist[N], topo[N]; void Init(int n){ this -> n = n; for(int i = 1; i <= n; ++ i) vis[i] = 0, dist[i] = - INF; } bool Topo_Sort(){ //拓撲排序 for(int i = 1; i <= n; ++ i){
if(in[i] == 0){ Q.push( i ); vis[i] = true; dist[i] = 0; topo[tot++] = i; } } while(!Q.empty()){ int u = Q.front(); Q.pop(); for(int i = edge[u].size() - 1; i >= 0; -- i){ int v = edge[u][i].first; -- in[v]; if(in[v] == 0 && !vis[v]){ vis[v] = true; Q.push( v ); topo[tot++] = v; } } } return tot == n ? true : false; } int Get_Cpm(){ //求關鍵路徑 for(int i = 0; i < tot; ++ i){ int u = topo[i]; for(int j = edge[u].size() - 1; j >= 0; -- j){ int v = edge[u][j].first; int c = edge[u][j].second; if(dist[v] < dist[u] + c) dist[v] = dist[u] + c; } } int ans = 0; for(int i = 1; i <= n; i++) if(dist[i] > ans) ans = dist[i]; return ans; } }Topo; void Input_data(int &n, int &m){ int u, v, c; scanf("%d %d", &n, &m); Topo.Init( n ); for(int i = 1; i <= m; ++ i){ scanf("%d %d %d", &u, &v, &c); edge[u].push_back(MP(v, c)); ++ Topo.in[v]; } } int main(){ int T, n, m; scanf("%d", &T); while(T --){ Input_data(n, m); Topo.Topo_Sort(); printf("%d\n", Topo.Get_Cpm()); for(int i = 1; i <= n; ++ i) edge[i].clear(); } }

2017 ACM-ICPC 亞洲區(烏魯木齊賽區)網絡賽 H. Skiing