日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

信息学奥赛一本通 1345:【例4-6】香甜的黄油 | 洛谷 P1828 [USACO3.2]香甜的黄油 Sweet Butter

發布時間:2025/3/17 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 信息学奥赛一本通 1345:【例4-6】香甜的黄油 | 洛谷 P1828 [USACO3.2]香甜的黄油 Sweet Butter 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

【題目鏈接】

ybt 1345:【例4-6】香甜的黃油
洛谷 P1828 [USACO3.2]香甜的黃油 Sweet Butter

【題目考點】

1. 圖論 最短路徑

【解題思路】

將題目敘述轉為圖論概念,牧場為頂點,牧場間的路線為邊。該題一個頂點上有多頭牛,這個后面再考慮。
記有V個頂點,E條邊,有n頭牛,每頭牛所在頂點為v1,v2,...vnv_1,v_2,...v_nv1?,v2?,...vn?d(i,j)d(i,j)d(i,j)為頂點i,j間的最短路徑長度。
題目要問的問題是,選擇一個頂點c,使得∑i=1nd(vi,c)\sum_{i=1}^nd(v_i,c)i=1n?d(vi?,c)最小。
如果已知每頭牛所在頂點到其它任意頂點的最短路徑長度,那么接下來就可以遍歷所有頂點,記遍歷到的頂點為i,選擇頂點i為放糖的地方,求所有牛所在頂點到頂點i的最短路徑加和,這一步的復雜度為O(V?n)O(V\cdot n)O(V?n)
問題落在如何求每頭牛所在頂點到其它任意頂點的最短路徑。

  • 使用Floyd算法,求所有頂點間的最短路徑長度。題目給定頂點數(牧場數)最大為800,Floyd算法的復雜度為O(V3)O(V^3)O(V3)8003=5.12?108800^3=5.12*10^88003=5.12?108,運算次數在10710^7107以下可以保證不會超時,復雜度達到10810^8108數量級很可能會超時,所以不能用Floyd算法。
    如果用單源最短路徑算法,需要對每頭牛所在頂點跑一次單源最短路徑算法。算法整體復雜度為:O(n)O(n)O(n)乘以所用的單源最短路徑算法的復雜度。
  • 考慮使用樸素Dijkstra算法,整體復雜度為O(n?V2)O(n\cdot V^2)O(n?V2),計算500?8002=3.2?108500*800^2=3.2*10^8500?8002=3.2?108,不可行。
  • 使用Dijkstra堆優化算法,整體復雜度為O(n?ElogE)O(n\cdot ElogE)O(n?ElogE),題目中邊數最多約為1500,計算500?1500?log21500≈8.25?106500*1500*log_21500\approx8.25*10^6500?1500?log2?15008.25?106,可行。
  • 使用SPFA算法,復雜度為O(kE)O(kE)O(kE),k為每個頂點平均入隊次數,在稀疏圖中一般小于2,可以認為等于2。用SPFA算法做該問題,整體復雜度為O(n?kE)O(n\cdot kE)O(n?kE),計算500?2?1500=1.5?106500*2*1500 = 1.5*10^6500?2?1500=1.5?106,可行。

以上是思考過程,該題做法為:

  • 通過Dijkstra堆優化算法或SPFA算法求出每個牛所在頂點到其它所有頂點的最短路徑
  • 遍歷每個頂點v,求每個牛所在頂點到v的最短路徑長度乘以那里牛的數量,再加和。求這些加和中的最小值。
  • 【題解代碼】

    解法1:Dijkstra堆優化算法

    #include<bits/stdc++.h> using namespace std; #define N 805 #define INF 0x3f3f3f3f struct Pair {int v, d;Pair(){}Pair(int a, int b):v(a),d(b){}bool operator < (const Pair &b) const{return b.d < d;} }; struct Edge {int t, w;Edge(){}Edge(int a, int b):t(a),w(b){} }; int n, p, c; bool vis[N]; int dis[N][N];//dis[i][j]:i到j的最短路徑長度 int place[N];//place[i]:牛i所在的頂點 vector<Edge> edge[N]; void initGraph() {int f, t, w;cin >> n >> p >> c;for(int i = 1; i <= n; ++i)cin >> place[i];for(int i = 1; i <= c; ++i){cin >> f >> t >> w;edge[f].push_back(Edge(t, w));edge[t].push_back(Edge(f, w));} } void dijkstra(int v0) {memset(vis, 0, sizeof(vis));priority_queue<Pair> pq;dis[v0][v0] = 0;pq.push(Pair(v0, 0));while(pq.empty() == false){int u = pq.top().v;pq.pop();if(vis[u])continue;vis[u] = true;for(int i = 0; i < edge[u].size(); ++i){int v = edge[u][i].t, w = edge[u][i].w;if(vis[v] == false && dis[v0][v] > dis[v0][u] + w){dis[v0][v] = dis[v0][u] + w;pq.push(Pair(v, dis[v0][v]));}}} } int main() {int v0, sum, ans = INF;initGraph();memset(dis, 0x3f, sizeof(dis));for(int i = 1; i <= n; ++i){v0 = place[i];//起點 if(dis[v0][v0] == INF)//如果該頂點的單源最短路徑問題沒有求過了 dijkstra(v0);}for(int i = 1; i <= p; ++i){//在頂點i放糖 sum = 0;for(int j = 1; j <= n; ++j)sum += dis[place[j]][i];ans = min(ans, sum);}cout << ans;return 0; }

    解法2:SPFA算法

    #include<bits/stdc++.h> using namespace std; #define N 805 #define INF 0x3f3f3f3f struct Pair {int v, d;Pair(){}Pair(int a, int b):v(a),d(b){}bool operator < (const Pair &b) const{return b.d < d;} }; struct Edge {int t, w;Edge(){}Edge(int a, int b):t(a),w(b){} }; int n, p, c; bool vis[N]; int dis[N][N];//dis[i][j]:i到j的最短路徑長度 int place[N];//place[i]:牛i所在的頂點 vector<Edge> edge[N]; void initGraph() {int f, t, w;cin >> n >> p >> c;for(int i = 1; i <= n; ++i)cin >> place[i];for(int i = 1; i <= c; ++i){cin >> f >> t >> w;edge[f].push_back(Edge(t, w));edge[t].push_back(Edge(f, w));} } void spfa(int v0) {memset(vis, 0, sizeof(vis));queue<int> que;dis[v0][v0] = 0;que.push(v0);vis[v0] = true;while(que.empty() == false){int u = que.front();que.pop();vis[u] = false;for(int i = 0; i < edge[u].size(); ++i){int v = edge[u][i].t, w = edge[u][i].w;if(dis[v0][v] > dis[v0][u] + w){dis[v0][v] = dis[v0][u] + w;if(vis[v] == false){que.push(v);vis[v] = true;}}}} } int main() {int v0, sum, ans = INF;initGraph();memset(dis, 0x3f, sizeof(dis));for(int i = 1; i <= n; ++i){v0 = place[i];//起點 if(dis[v0][v0] == INF)//如果該頂點的單源最短路徑問題沒有求過了 spfa(v0);}for(int i = 1; i <= p; ++i){//在頂點i放糖 sum = 0;for(int j = 1; j <= n; ++j)sum += dis[place[j]][i];ans = min(ans, sum);}cout << ans;return 0; }

    總結

    以上是生活随笔為你收集整理的信息学奥赛一本通 1345:【例4-6】香甜的黄油 | 洛谷 P1828 [USACO3.2]香甜的黄油 Sweet Butter的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。