題解/算法 {2279. 网络战争}

題解/算法 {2279. 网络战争}

@LINK: https://www.acwing.com/problem/content/description/2281/;

01分數規劃 求最小值, 定義二分函數為... <= mid, (Ei - mid)的和 <= 0, 因此我們得到一個新的無向圖G0 他每條邊的權值 等於原圖中邊權-= mid;
問題轉換為: 在G0中, 是否可以找到點S,T的一個(邊權之和<=0的)邊割集; 再轉換為: 找到邊割集的邊權和的最小值;

通過最大流等於最小割定理 可以解決這個問題, 因爲最大流所得到的最小割(即一個邊割集) 這個邊割集 可以對應到無向圖的情況, 需要做以下轉換:
0: 把負權邊給處理掉(因爲流網絡不允許有負權邊), 所有的<=0的邊 一定是可以放到最小的邊割集, 因此 令ANS(邊割集的最小和): 所有負權邊的和, 然後把這條邊給去掉 也就是將他的邊權(容量)置爲0; 令此時這個無向圖為G0;
1: 將無向圖G0轉換成有向圖G1(因爲流網絡必須是有向圖), 一個無向邊 對應2條有向邊;
2: 此時這個有向圖G1 求最大流(他雖然是這個有向圖的最小邊割集的值 但其實他也是G0的最小邊割集;
. 首先, 最大流等於最小割(割邊都是滿流的) 因此我們求出了G1的最小的邊割集; 其次 我們要證明 G1的最小割等於G0的最小割 參見@LINK: (https://editor.csdn.net/md/?not_checkout=1&articleId=136381246)-(@LOC_0);
. ANS += 最大流, 現在ANS就是答案(最小的邊割集), 判斷ANS <= 0即可;

無向邊a-b 對應a<->b兩條有向邊, 其實你的流網絡 就可以直接這樣建立 (是可以這樣做的), 但有點不符合常規流網絡的規定 因爲現在奇數編號的邊 就不再是反向邊了, 我們還是按照常規操作 繼續把a<->b對應到4條邊上;

void ___Solve( [[maybe_unused]] int ___testID){
    int N, M, S, T; cin>>N>>M>>S>>T; --S,--T;
    vector<pair<int,int> > Edges;
    static ___MaxFlow< Double> MaxFlow;
    MaxFlow.Initialize( N, M*2);
    FOR_( m, 1, M){
        int a, b, w; cin>>a>>b>>w;  --a,--b;
        MaxFlow.Add_edge( a, b, 0);  MaxFlow.Add_edge( b, a, 0);
        //> 記錄兩條*正向邊*的ID;
        Edges.emplace_back( MaxFlow.G_res.EdgesCount - 2, w);  Edges.emplace_back( MaxFlow.G_res.EdgesCount - 4, w);
    }
    
{ // 浮点数二分
    auto __check_success = [&]( Double _mid)->bool{ // 檢查最小割是否`<=mid`;
        Double minCut = 0;
        MaxFlow.Clear_flow();
        for( auto & e : Edges){
            auto & edge = MaxFlow.G_res.Weight[ e.first];
            auto w = Double(e.second) - _mid;
            if( w <= 0){ minCut += w; edge = 0;}
            else{ edge = w;}
        }
        minCut /= 2; // 注意這裏!!! 因爲一個無向邊對應了2條有向邊 上面會計算2次 所以要`/=2`;
        minCut += MaxFlow.Work( S, T);
        return minCut <= 0;
    };
  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值