調和のとれた軍隊

調和のとれた軍隊

制限時間:1秒   メモリ制限:128メガバイト

タイトル説明

今、ボブは、彼が調和のとれた軍隊の一般的である面白いゲームをプレイしています。この軍隊で兵士をNがあります。各兵士は2つの職業、メイジや戦士の1にする必要があります。組み合わせの能力を持つ兵士のm個のペアがあります。組み合わせの能力の3種類があります。ペアの2人の兵士が、両方の戦士であれば、軍の力を増加することでしょう。ペアの2人の兵士が、両方のメイジであれば、軍の力は、cによって増加されるだろう。そうしないと軍の力はbだけ増加されるだろう、とbが保証され、/ 4 + C / 3 =その4 | Aおよび3 | C。あなたの仕事は、出力にボブが兵士の職業を配置することで増やすことができる最大電力です。

24 | 12と8 | B例えば、3、Bを分割することを意味|シンボルがあることに注意してください。

エントリー

複数のテストケースがあります。
各ケースは、2つの正の整数N(n≤500)及びm(m≤104)を含む行から始まります。
次のm行で、各行は、5つの正の整数、U、V、A、B、C(1≤uが含ま、v≤n、Uは、V≠、1≤a、106×c≤4、+ B = / 4 C / 3)、表す兵士uとvはペア(u、v)が複数回表示されないことを保証組み合わせ能力を持っています。
すべてのテストケースにおけるnの合計は、5×103より大きくない、すべてのテストケースにおけるmの合計が5×104よりも大きくないことが保証されます。

輸出

各テストケースのために、最大電力ボブを含む出力1行兵士の職業を配置することにより増加させることができます。

サンプル入力

3 2 
1 2 8 3 3 
2 3 4 3 6

サンプル出力

12

質問の意味:nは2つの職業を配置する兵士、Mの関係、兵士約2辺の間の仕事上の付き合いの寄与との関係、および最大の貢献を求めているがあります。
最小カットは良い質問、印、それを構築する図。アイデアリファレンスソリューション:

最小限の関係を持つ2つの点で、ソース点xは、それぞれ、2つの職業を選択し、次にあなたが最初の貢献のすべてを追加することができますミーティング点Tにもエッジにも、エッジをsの各兵士のための点xを確立図に示すように、カットをモデル化します。

設けられた3つのサイドAへの寄与の種類; B; C、次式が得られる:
A + B = A + B(X、Yは、メイジから選択されます)

C + D = C + B(x、yは戦士を選択しています)

A + D + E = A + C(xがyを戦士から選択され、メイジから選択されます)

B + C + E = A + C(xは戦士から選択され、Yは、メイジから選択されます)

解の集合はE = -B +(A + C)/ 2、2つの点が全てに関連して、C = D =(C + B)/ 2、= B =(A + B)/ 2が得られます図合併、マイナス最小の数字はすべて寄付で切断することができます。

#include <ビット/ STDC ++ H>
 に#define N 505
 使用して 名前空間STDを、

typedef 構造体
{ 
    INT 次へ。
    長い 長い流れ。
} SS。

SS EDG [N * N]。
INT now_edge = 0 、S、T。
int型のヘッド[N]。

ボイド addedge(INT U、INT V、長い 長いフロー)
{ 
    EDG [now_edge] = (SS){V、ヘッド[U]、フロー}。
    ヘッド[U] = now_edge ++ 

    EDG [now_edge] =(SS){U、ヘッド[V]、0}。
    ヘッド[V] = now_edge ++ 
} 

int型DIS [N]を。

BOOL BFS()
{ 
    memsetの(DIS、0はsizeof (DIS))。
    キュー < 整数 > Q; 
    q.push(S); 
    DIS [S] = 1 

    しばらく(!q.empty())
    { 
        int型になりました= q.front(); 
        q.pop(); 
        以下のためにint型 I =ヘッド[今];!I = - 1 ; I = EDG [I] .next)
        { 
            SS&E = EDG [I]。
            もし(e.flow> 0 && DIS [e.to] == 0 
            { 
                DIS [e.to] = DIS [今] + 1 
                q.push(e.to)。
            } 
        } 
    } 

    もし(DIS [T] == 0戻り 0 ;
    リターン 1 ; 
} 

INT 現在[N]。
長い 長い DFS(INT X、長い 長いmaxflow)
{ 
    場合(X == T)戻りmaxflow。
//     のprintf( "%D%LLD \ n"、X、maxflow)。
    int型 - ;!I = I [x]は、現在= 1 ; I = EDG [I] .next)
    { 
        [X]電流 = I。
        SS&E = EDG [I]。
        もし(e.flow> 0 && DIS [e.to] == DIS [X] + 1 
        { 
            長い 長いフロー= DFS(e.to、分(maxflow、e.flow))。
            もし(!流れる= 0 
            { 
                e.flow - = 流量; 
                EDG [I ^ 1 ] .flow + = 流;
                リターンフロー; 
            }
        } 
    } 
    戻り 0 
} 

長い dinic()
{ 
    長い 長い ANS = 0 、流量;
    ながら(BFS())
    { 
        ためint型 I = 0、電流[I] = iが++; iがNを<)[i]のヘッドと、
        一方、(フロー= DFS(S、LLONG_MAX / 2))ANS + = 流量; 
    } 
    戻りANS。
} 

ボイドのinit()
{ 
    ためint型 i = 0 ; iがNを<; I ++)はヘッドを[I] = - 1 
    now_edge = 0 ; 
} 

int型マップ[N]、[N]を。

INT のmain()
{ 
    int型N、M。
    一方、(scanf関数(" %D%dの"、&​​N、&M)== 2 
    { 
        INIT()。
        以下のためにint型 i = 0 ; iが<= N + 2、iは++ のためにINT J = 0 ; J <= N + 2、J ++)地図[I] [J] = 0 ; 

        長い 長い ANS = 0 ; 

        S = N + 1 
        T = S + 1 

        一方、(M-- 
        { 
            int型、U、V、A、B、C。
            scanf関数(" %D%D%D%D%D "、およびuは、&​​V、&A、&B、&C)。
            ANS + = A + B + C。
            地図[S] [U] + = A + B。
            地図[S] [V] + = A + B。
            地図[U] [T] + = C + B。
            地図[V] [T] + = C + B。
            地図[U] [V] + = A + C- 2 * B。
            地図[V] [U] + = A + C- 2 *のB。
        }

        のためのINTi = 1 ; iが<=は、n + 2、iは++ のためにINT J = 1 ; J <= N + 2、J ++)場合(地図[I] [J])addedge(I、J、マップ[I] [J] ); 

        printf(" %LLDする\ n "、ANS-dinic()/ 2 )。
    } 
    戻り 0 
}
コードの表示

 

おすすめ

転載: www.cnblogs.com/tian-luo/p/11240796.html