CCF習題 201703-4 地鐵修建(dijkstra 或者 最小生成樹)
阿新 • • 發佈:2018-12-24
題意:
很水很水的一道題目, 但自己也很水, 沒得全分= = ~~~
求使得1和n 連通得一條路中最大路權最小值。
思路:
多個思路:
1. 修改dijkstra,把判斷距離改成判斷 最大路權即可。
2. 最小生成樹,直接按照最小生成樹做,當1和n 連通時就找到答案了,因為這時候肯定是邊最小的。
迪傑斯特拉版本程式碼:
#include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <queue> #define Siz(x) (int)x.size() using namespace std; const int maxn = 100000 + 10; int n,m; struct Edge{ int f,t,w; Edge(int f=0,int t = 0,int w = 0):f(f),t(t),w(w){} }; struct Node{ int d,u; Node(int d = 0,int u = 0):d(d),u(u){} bool operator < (const Node& rhs) const { return d > rhs.d; } }; vector<Edge>edges; vector<int>g[maxn]; int sz = 0; priority_queue<Node>q; bool vis[maxn]; int dis[maxn]; int bfs(){ q.push(Node(0,1)); for (int i = 2; i <= n; ++i)dis[i] = 0x3f3f3f3f; dis[1] = 0; while(!q.empty()){ Node o = q.top(); q.pop(); int u = o.u; int d = o.d; if (vis[u]) continue; vis[u] = 1; for (int i = 0; i < Siz(g[u]); ++i){ Edge& e = edges[g[u][i]]; int nd = d; if (e.w > nd)nd = e.w; if (nd < dis[e.t]){ dis[e.t] = nd; q.push(Node(nd,e.t)); } } } return dis[n]; } int main(){ scanf("%d %d",&n, &m); for (int i = 0; i < m; ++i){ int u,v,w; scanf("%d %d %d",&u, &v, &w); edges.push_back(Edge(u,v,w)); sz++; g[u].push_back(sz-1); edges.push_back(Edge(v,u,w)); sz++; g[v].push_back(sz-1); } printf("%d\n",bfs()); return 0; } /** 6 6 1 2 4 2 3 4 3 6 7 1 4 2 4 5 5 5 6 6 **/
最小生成樹程式碼:
問題描述#include <cstdio> #include <cstring> #include <algorithm> using namespace std; struct Node{ int u,v,w; bool operator < (const Node &rhs) const { return w < rhs.w; } void read(){ scanf("%d %d %d",&u, &v, &w); } }p[200000+10]; int fa[100000 + 10]; int find(int x){ return fa[x] == x?x:fa[x] = find(fa[x]); } int main(){ int n,m; scanf("%d %d",&n, &m); for (int i =1; i <= n; ++i)fa[i] = i; for (int i = 0; i < m; ++i){ p[i].read(); } sort(p,p+m); int ans = 0; int i; for (i = 0; i < m; ++i){ if (find(n) == find(1))break; fa[find(p[i].u) ] = find(p[i].v); } printf("%d\n",p[i-1].w); return 0; }
試題編號: | 201703-4 |
試題名稱: | 地鐵修建 |
時間限制: | 1.0s |
記憶體限制: | 256.0MB |
問題描述: |
問題描述
A市有n個交通樞紐,其中1號和n號非常重要,為了加強運輸能力,A市決定在1號到n號樞紐間修建一條地鐵。 地鐵由很多段隧道組成,每段隧道連線兩個交通樞紐。經過勘探,有m段隧道作為候選,兩個交通樞紐之間最多隻有一條候選的隧道,沒有隧道兩端連線著同一個交通樞紐。 現在有n家隧道施工的公司,每段候選的隧道只能由一個公司施工,每家公司施工需要的天數一致。而每家公司最多隻能修建一條候選隧道。所有公司同時開始施工。 作為專案負責人,你獲得了候選隧道的資訊,現在你可以按自己的想法選擇一部分隧道進行施工,請問修建整條地鐵最少需要多少天。 輸入格式 輸入的第一行包含兩個整數n, m,用一個空格分隔,分別表示交通樞紐的數量和候選隧道的數量。 第2行到第m+1行,每行包含三個整數a, b, c,表示樞紐a和樞紐b之間可以修建一條隧道,需要的時間為c天。 輸出格式 輸出一個整數,修建整條地鐵線路最少需要的天數。 樣例輸入 6 6 1 2 4 2 3 4 3 6 7 1 4 2 4 5 5 5 6 6 樣例輸出 6 樣例說明 可以修建的線路有兩種。 第一種經過的樞紐依次為1, 2, 3, 6,所需要的時間分別是4, 4, 7,則整條地鐵線需要7天修完; 第二種經過的樞紐依次為1, 4, 5, 6,所需要的時間分別是2, 5, 6,則整條地鐵線需要6天修完。 第二種方案所用的天數更少。 評測用例規模與約定 對於20%的評測用例,1 ≤ n ≤ 10,1 ≤ m ≤ 20; 對於40%的評測用例,1 ≤ n ≤ 100,1 ≤ m ≤ 1000; 對於60%的評測用例,1 ≤ n ≤ 1000,1 ≤ m ≤ 10000,1 ≤ c ≤ 1000; 對於80%的評測用例,1 ≤ n ≤ 10000,1 ≤ m ≤ 100000; 對於100%的評測用例,1 ≤ n ≤ 100000,1 ≤ m ≤ 200000,1 ≤ a, b ≤ n,1 ≤ c ≤ 1000000。 所有評測用例保證在所有候選隧道都修通時1號樞紐可以通過隧道到達其他所有樞紐。 |