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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

算法提高课-图论-负环-AcWing 361. 观光奶牛:spfa判正环、负环、01分数规划、二分

發布時間:2025/4/5 编程问答 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 算法提高课-图论-负环-AcWing 361. 观光奶牛:spfa判正环、负环、01分数规划、二分 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

      • 題目分析
      • 題目鏈接

題目分析


來源:acwing
分析:

題目要求ΣfiΣgi\frac{\Sigma{f_i}}{\Sigma{g_i}}Σgi?Σfi??的最大值,這種問題稱為01分數規劃,通俗點說,就是一堆的和除以一堆的和,要求比值最大。

對于本題

我們可以通過二分來做,二分啥呢?就是對于一個環,二分一個mid值,判斷是否滿足ΣfiΣgi≥mid\frac{\Sigma{f_i}}{\Sigma{g_i}} \geq midΣgi?Σfi??mid,然后我們就可以來不斷更改二分的區間,直到找到ΣfiΣgi\frac{\Sigma{f_i}}{\Sigma{g_i}}Σgi?Σfi??的最大值。

思路確定了,那么具體如何實現呢?

ΣfiΣgi≥mid\frac{\Sigma{f_i}}{\Sigma{g_i}} \geq midΣgi?Σfi??mid 由于這里的邊都是正權邊,所以可以移項,變成 Σfi≥mid×Σgi{\Sigma{f_i}} \geq mid \times{\Sigma{g_i}}Σfi?mid×Σgi?
再變一下:

Σfi?mid×Σgi≥0{\Sigma{f_i}} - mid \times{\Sigma{g_i}} \geq0Σfi??mid×Σgi?0

將求和符號提出,亦等價于:

Σ(fi?mid×gi)≥0{\Sigma{(f_i} - mid \times{g_i})} \geq0Σ(fi??mid×gi?)0
如下建圖:

看完上圖,其實我們還能繼續推導:
Σ(fi?mid×gi)≥0{\Sigma{(f_i} - mid \times{g_i})} \geq0Σ(fi??mid×gi?)0 等價于 圖中存在正環
總結一下01分數規劃的套路:

  • 二分一個定值
  • 整理表達式,重新定義邊權
  • 套用常規的圖論算法(負環、最小生成樹等等)
  • 由于是求正環,本質上還是求負環,只不過最短路變成最長路。

    而且,邊權需要自定義,如上圖,邊權wf[t] - mid * wt[i],其中wf[t]表示t點的點權,wt[i]表示從t到i的邊權,這樣合起來作為該邊的邊權,相當于spfa求最最短路的邊權w[i].

    if(dist[j] < dist[t] + wf[t] - mid * wt[i]){dist[j] = dist[t] + wf[t] - mid * wt[i];cnt[j] = cnt[t] + 1; // 統計每個點最短路經過的邊數if(cnt[j] >= n) return true; //存在正環

    ac代碼

    #include<bits/stdc++.h> using namespace std; const int N = 1010, M = 5010; int n, m; int wf[N]; // 點權int h[N], e[M], wt[M], ne[M], idx; // wt[]是邊權 bool st[N]; double dist[N]; int cnt[N]; // 統計每個點最短路上邊的數量void add(int a, int b, int c){e[idx] = b, wt[idx] = c, ne[idx] = h[a], h[a] = idx ++; }// spfa判負環的模板(當然,這里是判正環,本質上是一樣的) bool check(double mid){// 求負環時不需要初始化distmemset(st, 0, sizeof st);memset(cnt, 0, sizeof cnt);queue<int> q;// 所有點都入隊for(int i = 1; i <= n; i ++){q.push(i);st[i] = true;}while(q.size()){auto t = q.front();q.pop();st[t] = false;for(int i = h[t]; ~i; i = ne[i]){int j = e[i];// 求正環,最長路if(dist[j] < dist[t] + wf[t] - mid * wt[i]){dist[j] = dist[t] + wf[t] - mid * wt[i];cnt[j] = cnt[t] + 1;if(cnt[j] >= n) return true; //存在正環if(!st[j]){st[j] = true;q.push(j); }}}}return false; }int main(){memset(h, -1, sizeof h);cin >> n >> m;for(int i = 1; i <= n; i ++) cin >> wf[i];while( m--){int a, b, c;cin >> a >> b >> c;add(a, b, c);}// 二分出來答案double l = 0, r = 1010;while( r - l > 1e-4){ // 經驗上來說和保留位數多兩位double mid = (l + r) / 2;if(check(mid)) l = mid;else r = mid;}printf("%.2lf\n", r); }

    題目鏈接

    https://www.acwing.com/problem/content/363/

    《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀

    總結

    以上是生活随笔為你收集整理的算法提高课-图论-负环-AcWing 361. 观光奶牛:spfa判正环、负环、01分数规划、二分的全部內容,希望文章能夠幫你解決所遇到的問題。

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